Coverage for pyVHDLModel/Concurrent.py: 45%
374 statements
« prev ^ index » next coverage.py v7.15.1, created at 2026-07-13 17:58 +0000
« prev ^ index » next coverage.py v7.15.1, created at 2026-07-13 17:58 +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.
35Concurrent defines all concurrent statements used in entities, architectures, generates and block statements.
36"""
37from typing import List, Dict, Union, Iterable, Generator, Optional as Nullable
39from pyTooling.Decorators import export, readonly
40from pyTooling.MetaClasses import ExtendedType
42from pyVHDLModel.Base import ModelEntity, LabeledEntityMixin, DocumentedEntityMixin, Range, BaseChoice, BaseCase, IfBranchMixin
43from pyVHDLModel.Base import ElsifBranchMixin, ElseBranchMixin, AssertStatementMixin, BlockStatementMixin, WaveformElement
44from pyVHDLModel.Regions import ConcurrentDeclarationRegionMixin
45from pyVHDLModel.Namespace import Namespace
46from pyVHDLModel.Name import Name
47from pyVHDLModel.Symbol import ComponentInstantiationSymbol, EntityInstantiationSymbol, ArchitectureSymbol, ConfigurationInstantiationSymbol
48from pyVHDLModel.Expression import BaseExpression, QualifiedExpression, FunctionCall, TypeConversion, Literal
49from pyVHDLModel.Association import AssociationItem, ParameterAssociationItem
50from pyVHDLModel.Interface import PortInterfaceItemMixin
51from pyVHDLModel.Common import Statement, ProcedureCallMixin, SignalAssignmentMixin, AllowBlackboxMixin
52from pyVHDLModel.Sequential import SequentialStatement, SequentialStatementsMixin, SequentialDeclarationsMixin
55ExpressionUnion = Union[
56 BaseExpression,
57 QualifiedExpression,
58 FunctionCall,
59 TypeConversion,
60 # ConstantOrSymbol, TODO: ObjectSymbol
61 Literal,
62]
65@export
66class ConcurrentStatement(Statement):
67 """A base-class for all concurrent statements."""
70@export
71class ConcurrentStatementsMixin(metaclass=ExtendedType, mixin=True):
72 """
73 A mixin-class for all language constructs supporting concurrent statements.
75 .. seealso::
77 .. todo:: concurrent declaration region
78 """
80 _statements: List[ConcurrentStatement]
82 _instantiations: Dict[str, 'Instantiation'] # TODO: add another instantiation class level for entity/configuration/component inst.
83 _blocks: Dict[str, 'ConcurrentBlockStatement']
84 _generates: Dict[str, 'GenerateStatement']
85 _hierarchy: Dict[str, Union['ConcurrentBlockStatement', 'GenerateStatement']]
87 def __init__(self, statements: Nullable[Iterable[ConcurrentStatement]] = None) -> None:
88 self._statements = []
90 self._instantiations = {}
91 self._blocks = {}
92 self._generates = {}
93 self._hierarchy = {}
95 if statements is not None:
96 for statement in statements:
97 self._statements.append(statement)
98 statement.Parent = self
100 @readonly
101 def Statements(self) -> List[ConcurrentStatement]:
102 return self._statements
104 def IterateInstantiations(self) -> Generator['Instantiation', None, None]:
105 for instance in self._instantiations.values():
106 yield instance
108 for block in self._blocks.values(): 108 ↛ 109line 108 didn't jump to line 109 because the loop on line 108 never started
109 yield from block.IterateInstantiations()
111 for generate in self._generates.values(): 111 ↛ 112line 111 didn't jump to line 112 because the loop on line 111 never started
112 yield from generate.IterateInstantiations()
114 # TODO: move into _init__
115 def IndexStatements(self) -> None:
116 for statement in self._statements:
117 if isinstance(statement, (EntityInstantiation, ComponentInstantiation, ConfigurationInstantiation)): 117 ↛ 119line 117 didn't jump to line 119 because the condition on line 117 was always true
118 self._instantiations[statement.NormalizedLabel] = statement
119 elif isinstance(statement, (ForGenerateStatement, IfGenerateStatement, CaseGenerateStatement)):
120 self._generates[statement.NormalizedLabel] = statement
121 statement.IndexStatement()
122 elif isinstance(statement, ConcurrentBlockStatement):
123 self._hierarchy[statement.NormalizedLabel] = statement
124 statement.IndexStatements()
127@export
128class Instantiation(ConcurrentStatement):
129 """
130 A base-class for all (component) instantiations.
131 """
133 _genericAssociations: List[AssociationItem]
134 _portAssociations: List[AssociationItem]
136 def __init__(
137 self,
138 label: str,
139 genericAssociations: Nullable[Iterable[AssociationItem]] = None,
140 portAssociations: Nullable[Iterable[AssociationItem]] = None,
141 parent: Nullable[ModelEntity] = None
142 ) -> None:
143 super().__init__(label, parent)
145 # TODO: extract to mixin
146 self._genericAssociations = []
147 if genericAssociations is not None: 147 ↛ 148line 147 didn't jump to line 148 because the condition on line 147 was never true
148 for association in genericAssociations:
149 self._genericAssociations.append(association)
150 association.Parent = self
152 # TODO: extract to mixin
153 self._portAssociations = []
154 if portAssociations is not None: 154 ↛ 155line 154 didn't jump to line 155 because the condition on line 154 was never true
155 for association in portAssociations:
156 self._portAssociations.append(association)
157 association.Parent = self
159 @readonly
160 def GenericAssociations(self) -> List[AssociationItem]:
161 return self._genericAssociations
163 @property
164 def PortAssociations(self) -> List[AssociationItem]:
165 return self._portAssociations
168@export
169class ComponentInstantiation(Instantiation):
170 """
171 Represents a component instantiation by referring to a component name.
173 .. admonition:: Example
175 .. code-block:: VHDL
177 inst : component Counter;
178 """
180 _component: ComponentInstantiationSymbol
182 def __init__(
183 self,
184 label: str,
185 componentSymbol: ComponentInstantiationSymbol,
186 genericAssociations: Nullable[Iterable[AssociationItem]] = None,
187 portAssociations: Nullable[Iterable[AssociationItem]] = None,
188 parent: Nullable[ModelEntity] = None
189 ) -> None:
190 super().__init__(label, genericAssociations, portAssociations, parent)
192 self._component = componentSymbol
193 componentSymbol.Parent = self
195 @property
196 def Component(self) -> ComponentInstantiationSymbol:
197 return self._component
200@export
201class EntityInstantiation(Instantiation):
202 """
203 Represents an entity instantiation by referring to an entity name with optional architecture name.
205 .. admonition:: Example
207 .. code-block:: VHDL
209 inst : entity work. Counter;
210 """
212 _entity: EntityInstantiationSymbol
213 _architecture: ArchitectureSymbol
215 def __init__(
216 self,
217 label: str,
218 entitySymbol: EntityInstantiationSymbol,
219 architectureSymbol: Nullable[ArchitectureSymbol] = None,
220 genericAssociations: Nullable[Iterable[AssociationItem]] = None,
221 portAssociations: Nullable[Iterable[AssociationItem]] = None,
222 parent: Nullable[ModelEntity] = None
223 ) -> None:
224 super().__init__(label, genericAssociations, portAssociations, parent)
226 self._entity = entitySymbol
227 entitySymbol.Parent = self
229 self._architecture = architectureSymbol
230 if architectureSymbol is not None: 230 ↛ 231line 230 didn't jump to line 231 because the condition on line 230 was never true
231 architectureSymbol.Parent = self
233 @property
234 def Entity(self) -> EntityInstantiationSymbol:
235 return self._entity
237 @property
238 def Architecture(self) -> ArchitectureSymbol:
239 return self._architecture
242@export
243class ConfigurationInstantiation(Instantiation):
244 """
245 Represents a configuration instantiation by referring to a configuration name.
247 .. admonition:: Example
249 .. code-block:: VHDL
251 inst : configuration Counter;
252 """
254 _configuration: ConfigurationInstantiationSymbol
256 def __init__(
257 self,
258 label: str,
259 configurationSymbol: ConfigurationInstantiationSymbol,
260 genericAssociations: Nullable[Iterable[AssociationItem]] = None,
261 portAssociations: Nullable[Iterable[AssociationItem]] = None,
262 parent: Nullable[ModelEntity] = None
263 ) -> None:
264 super().__init__(label, genericAssociations, portAssociations, parent)
266 self._configuration = configurationSymbol
267 configurationSymbol.Parent = self
269 @property
270 def Configuration(self) -> ConfigurationInstantiationSymbol:
271 return self._configuration
274@export
275class ProcessStatement(ConcurrentStatement, SequentialDeclarationsMixin, SequentialStatementsMixin, DocumentedEntityMixin):
276 """
277 Represents a process statement with sensitivity list, sequential declaration region and sequential statements.
279 .. admonition:: Example
281 .. code-block:: VHDL
283 proc: process(Clock)
284 -- sequential declarations
285 begin
286 -- sequential statements
287 end process;
288 """
290 _sensitivityList: List[Name] # TODO: implement a SignalSymbol
292 def __init__(
293 self,
294 label: Nullable[str] = None,
295 declaredItems: Nullable[Iterable] = None,
296 statements: Nullable[Iterable[SequentialStatement]] = None,
297 sensitivityList: Nullable[Iterable[Name]] = None,
298 documentation: Nullable[str] = None,
299 parent: Nullable[ModelEntity] = None
300 ) -> None:
301 super().__init__(label, parent)
302 SequentialDeclarationsMixin.__init__(self, declaredItems)
303 SequentialStatementsMixin.__init__(self, statements)
304 DocumentedEntityMixin.__init__(self, documentation)
306 if sensitivityList is None:
307 self._sensitivityList = None
308 else:
309 self._sensitivityList = [] # TODO: convert to dict
310 for signalSymbol in sensitivityList:
311 self._sensitivityList.append(signalSymbol)
312 # signalSymbol._parent = self # FIXME: currently str are provided
314 @property
315 def SensitivityList(self) -> List[Name]:
316 return self._sensitivityList
319@export
320class ConcurrentProcedureCall(ConcurrentStatement, ProcedureCallMixin):
321 def __init__(
322 self,
323 label: str,
324 procedureName: Name,
325 parameterMappings: Nullable[Iterable[ParameterAssociationItem]] = None,
326 parent: Nullable[ModelEntity] = None
327 ) -> None:
328 super().__init__(label, parent)
329 ProcedureCallMixin.__init__(self, procedureName, parameterMappings)
332@export
333class ConcurrentBlockStatement(ConcurrentStatement, BlockStatementMixin, LabeledEntityMixin, ConcurrentDeclarationRegionMixin, ConcurrentStatementsMixin, DocumentedEntityMixin, AllowBlackboxMixin):
334 _portItems: List[PortInterfaceItemMixin]
336 _namespace: Namespace
338 def __init__(
339 self,
340 label: str,
341 portItems: Nullable[Iterable[PortInterfaceItemMixin]] = None,
342 declaredItems: Nullable[Iterable] = None,
343 statements: Iterable['ConcurrentStatement'] = None,
344 documentation: Nullable[str] = None,
345 allowBlackbox: Nullable[bool] = None,
346 parent: Nullable[ModelEntity] = None
347 ) -> None:
348 super().__init__(label, parent)
350 self._namespace = Namespace(self._normalizedLabel)
351 if parent is not None:
352 self._namespace.ParentNamespace = parent._namespace
354 BlockStatementMixin.__init__(self)
355 LabeledEntityMixin.__init__(self, label)
356 ConcurrentDeclarationRegionMixin.__init__(self, declaredItems)
357 ConcurrentStatementsMixin.__init__(self, statements)
358 DocumentedEntityMixin.__init__(self, documentation)
359 AllowBlackboxMixin.__init__(self, allowBlackbox)
361 # TODO: extract to mixin
362 self._portItems = []
363 if portItems is not None:
364 for item in portItems:
365 self._portItems.append(item)
366 item.Parent = self
368 @ConcurrentStatement.Parent.setter
369 def Parent(self, parent: ModelEntity) -> None:
370 ConcurrentStatement.Parent.fset(self, parent)
372 self._namespace.ParentNamespace = parent._namespace
374 @property
375 def PortItems(self) -> List[PortInterfaceItemMixin]:
376 return self._portItems
379@export
380class GenerateBranch(ModelEntity, ConcurrentDeclarationRegionMixin, ConcurrentStatementsMixin, AllowBlackboxMixin):
381 """
382 A base-class for all branches in a generate statements.
384 .. seealso::
386 * :class:`If-generate branch <pyVHDLModel.Concurrent.IfGenerateBranch>`
387 * :class:`Elsif-generate branch <pyVHDLModel.Concurrent.ElsifGenerateBranch>`
388 * :class:`Else-generate branch <pyVHDLModel.Concurrent.ElseGenerateBranch>`
389 """
391 _alternativeLabel: Nullable[str]
392 _normalizedAlternativeLabel: Nullable[str]
394 _namespace: Namespace
396 def __init__(
397 self,
398 declaredItems: Nullable[Iterable] = None,
399 statements: Nullable[Iterable[ConcurrentStatement]] = None,
400 alternativeLabel: Nullable[str] = None,
401 allowBlackbox: Nullable[bool] = None,
402 parent: Nullable[ModelEntity] = None
403 ) -> None:
404 super().__init__(parent)
406 self._alternativeLabel = alternativeLabel
407 self._normalizedAlternativeLabel = alternativeLabel.lower() if alternativeLabel is not None else None
409 self._namespace = Namespace(self._normalizedAlternativeLabel)
410 if parent is not None:
411 self._namespace.ParentNamespace = parent._namespace
413 ConcurrentDeclarationRegionMixin.__init__(self, declaredItems)
414 ConcurrentStatementsMixin.__init__(self, statements)
415 AllowBlackboxMixin.__init__(self, allowBlackbox)
417 @property
418 def AlternativeLabel(self) -> Nullable[str]:
419 return self._alternativeLabel
421 @property
422 def NormalizedAlternativeLabel(self) -> Nullable[str]:
423 return self._normalizedAlternativeLabel
426@export
427class IfGenerateBranch(GenerateBranch, IfBranchMixin):
428 """
429 Represents if-generate branch in a generate statement with a concurrent declaration region and concurrent statements.
431 .. admonition:: Example
433 .. code-block:: VHDL
435 gen: if condition generate
436 -- concurrent declarations
437 begin
438 -- concurrent statements
439 elsif condition generate
440 -- ...
441 else generate
442 -- ...
443 end generate;
444 """
446 def __init__(
447 self,
448 condition: ExpressionUnion,
449 declaredItems: Nullable[Iterable] = None,
450 statements: Nullable[Iterable[ConcurrentStatement]] = None,
451 alternativeLabel: Nullable[str] = None,
452 allowBlackbox: Nullable[bool] = None,
453 parent: Nullable[ModelEntity] = None
454 ) -> None:
455 super().__init__(declaredItems, statements, alternativeLabel, allowBlackbox, parent)
456 IfBranchMixin.__init__(self, condition)
459@export
460class ElsifGenerateBranch(GenerateBranch, ElsifBranchMixin):
461 """
462 Represents elsif-generate branch in a generate statement with a concurrent declaration region and concurrent statements.
464 .. admonition:: Example
466 .. code-block:: VHDL
468 gen: if condition generate
469 -- ...
470 elsif condition generate
471 -- concurrent declarations
472 begin
473 -- concurrent statements
474 else generate
475 -- ...
476 end generate;
477 """
479 def __init__(
480 self,
481 condition: ExpressionUnion,
482 declaredItems: Nullable[Iterable] = None,
483 statements: Nullable[Iterable[ConcurrentStatement]] = None,
484 alternativeLabel: Nullable[str] = None,
485 allowBlackbox: Nullable[bool] = None,
486 parent: Nullable[ModelEntity] = None
487 ) -> None:
488 super().__init__(declaredItems, statements, alternativeLabel, allowBlackbox, parent)
489 ElsifBranchMixin.__init__(self, condition)
492@export
493class ElseGenerateBranch(GenerateBranch, ElseBranchMixin):
494 """
495 Represents else-generate branch in a generate statement with a concurrent declaration region and concurrent statements.
497 .. admonition:: Example
499 .. code-block:: VHDL
501 gen: if condition generate
502 -- ...
503 elsif condition generate
504 -- ...
505 else generate
506 -- concurrent declarations
507 begin
508 -- concurrent statements
509 end generate;
510 """
512 def __init__(
513 self,
514 declaredItems: Nullable[Iterable] = None,
515 statements: Nullable[Iterable[ConcurrentStatement]] = None,
516 alternativeLabel: Nullable[str] = None,
517 allowBlackbox: Nullable[bool] = None,
518 parent: Nullable[ModelEntity] = None
519 ) -> None:
520 super().__init__(declaredItems, statements, alternativeLabel, allowBlackbox, parent)
521 ElseBranchMixin.__init__(self)
524@export
525class GenerateStatement(ConcurrentStatement, AllowBlackboxMixin):
526 """
527 A base-class for all generate statements.
529 .. seealso::
531 * :class:`If...generate statement <pyVHDLModel.Concurrent.IfGenerateStatement>`
532 * :class:`Case...generate statement <pyVHDLModel.Concurrent.CaseGenerateStatement>`
533 * :class:`For...generate statement <pyVHDLModel.Concurrent.ForGenerateStatement>`
534 """
536 def __init__(
537 self,
538 label: Nullable[str] = None,
539 allowBlackbox: Nullable[bool] = None,
540 parent: Nullable[ModelEntity] = None
541 ) -> None:
542 super().__init__(label, parent)
543 AllowBlackboxMixin.__init__(self, allowBlackbox)
545 # @mustoverride
546 def IterateInstantiations(self) -> Generator[Instantiation, None, None]:
547 raise NotImplementedError()
549 # @mustoverride
550 def IndexStatement(self) -> None:
551 raise NotImplementedError()
554@export
555class IfGenerateStatement(GenerateStatement):
556 """
557 Represents an if...generate statement.
559 .. admonition:: Example
561 .. code-block:: VHDL
563 gen: if condition generate
564 -- ...
565 elsif condition generate
566 -- ...
567 else generate
568 -- ...
569 end generate;
571 .. seealso::
573 * :class:`Generate branch <pyVHDLModel.Concurrent.GenerateBranch>` base-class
574 * :class:`If-generate branch <pyVHDLModel.Concurrent.IfGenerateBranch>`
575 * :class:`Elsif-generate branch <pyVHDLModel.Concurrent.ElsifGenerateBranch>`
576 * :class:`Else-generate branch <pyVHDLModel.Concurrent.ElseGenerateBranch>`
577 """
579 _ifBranch: IfGenerateBranch
580 _elsifBranches: List[ElsifGenerateBranch]
581 _elseBranch: Nullable[ElseGenerateBranch]
583 def __init__(
584 self,
585 label: str,
586 ifBranch: IfGenerateBranch,
587 elsifBranches: Nullable[Iterable[ElsifGenerateBranch]] = None,
588 elseBranch: Nullable[ElseGenerateBranch] = None,
589 allowBlackbox: Nullable[bool] = None,
590 parent: Nullable[ModelEntity] = None
591 ) -> None:
592 super().__init__(label, allowBlackbox, parent)
594 self._ifBranch = ifBranch
595 ifBranch.Parent = self
597 self._elsifBranches = []
598 if elsifBranches is not None:
599 for branch in elsifBranches:
600 self._elsifBranches.append(branch)
601 branch.Parent = self
603 if elseBranch is not None:
604 self._elseBranch = elseBranch
605 elseBranch.Parent = self
606 else:
607 self._elseBranch = None
609 @GenerateStatement.Parent.setter
610 def Parent(self, parent: ModelEntity) -> None:
611 from pyVHDLModel.DesignUnit import Architecture
613 GenerateStatement.Parent.fset(self, parent)
615 # Connect namespaces
616 namespace = self._ifBranch._namespace
617 namespace.ParentNamespace = parent._namespace
618 if namespace._name == "":
619 namespace._name = self._normalizedLabel
621 for elseBranch in self._elsifBranches:
622 elseBranch._namespace.ParentNamespace = parent._namespace
624 if self._elseBranch is not None:
625 self._elseBranch._namespace.ParentNamespace = parent._namespace
627 @property
628 def IfBranch(self) -> IfGenerateBranch:
629 return self._ifBranch
631 @property
632 def ElsifBranches(self) -> List[ElsifGenerateBranch]:
633 return self._elsifBranches
635 @property
636 def ElseBranch(self) -> Nullable[ElseGenerateBranch]:
637 return self._elseBranch
639 def IterateInstantiations(self) -> Generator[Instantiation, None, None]:
640 yield from self._ifBranch.IterateInstantiations()
641 for branch in self._elsifBranches:
642 yield from branch.IterateInstantiations()
643 if self._elseBranch is not None:
644 yield from self._ifBranch.IterateInstantiations()
646 def IndexStatement(self) -> None:
647 self._ifBranch.IndexStatements()
648 for branch in self._elsifBranches:
649 branch.IndexStatements()
650 if self._elseBranch is not None:
651 self._elseBranch.IndexStatements()
654@export
655class ConcurrentChoice(BaseChoice):
656 """A base-class for all concurrent choices (in case...generate statements)."""
659@export
660class IndexedGenerateChoice(ConcurrentChoice):
661 _expression: ExpressionUnion
663 def __init__(self, expression: ExpressionUnion, parent: Nullable[ModelEntity] = None) -> None:
664 super().__init__(parent)
666 self._expression = expression
667 expression.Parent = self
669 @property
670 def Expression(self) -> ExpressionUnion:
671 return self._expression
673 def __str__(self) -> str:
674 return str(self._expression)
677@export
678class RangedGenerateChoice(ConcurrentChoice):
679 _range: 'Range'
681 def __init__(self, rng: 'Range', parent: Nullable[ModelEntity] = None) -> None:
682 super().__init__(parent)
684 self._range = rng
685 rng.Parent = self
687 @property
688 def Range(self) -> 'Range':
689 return self._range
691 def __str__(self) -> str:
692 return str(self._range)
695@export
696class ConcurrentCase(BaseCase, LabeledEntityMixin, ConcurrentDeclarationRegionMixin, ConcurrentStatementsMixin, AllowBlackboxMixin):
697 _namespace: Namespace
699 def __init__(
700 self,
701 declaredItems: Nullable[Iterable] = None,
702 statements: Nullable[Iterable[ConcurrentStatement]] = None,
703 alternativeLabel: Nullable[str] = None,
704 allowBlackbox: Nullable[bool] = None,
705 parent: Nullable[ModelEntity] = None
706 ) -> None:
707 super().__init__(parent)
708 LabeledEntityMixin.__init__(self, alternativeLabel)
710 # TODO: Why not handover self?
711 # This allows access to Label and NormalizedLabel, also to create a full instance path in case a lookup goes wrong.
712 # TODO: How about a WithNamespaceMixin class?
713 self._namespace = Namespace(self._normalizedLabel)
714 if parent is not None:
715 self._namespace.ParentNamespace = parent._namespace
717 ConcurrentDeclarationRegionMixin.__init__(self, declaredItems)
718 ConcurrentStatementsMixin.__init__(self, statements)
719 AllowBlackboxMixin.__init__(self, allowBlackbox)
722@export
723class GenerateCase(ConcurrentCase):
724 _choices: List[ConcurrentChoice]
726 def __init__(
727 self,
728 choices: Iterable[ConcurrentChoice],
729 declaredItems: Nullable[Iterable] = None,
730 statements: Nullable[Iterable[ConcurrentStatement]] = None,
731 alternativeLabel: Nullable[str] = None,
732 allowBlackbox: Nullable[bool] = None,
733 parent: Nullable[ModelEntity] = None
734 ) -> None:
735 super().__init__(declaredItems, statements, alternativeLabel, allowBlackbox, parent)
737 # TODO: move to parent or grandparent
738 self._choices = []
739 if choices is not None:
740 for choice in choices:
741 self._choices.append(choice)
742 choice.Parent = self
744 # TODO: move to parent or grandparent
745 @property
746 def Choices(self) -> List[ConcurrentChoice]:
747 return self._choices
749 def __str__(self) -> str:
750 return "when {choices} =>".format(choices=" | ".join(str(c) for c in self._choices))
753@export
754class OthersGenerateCase(ConcurrentCase):
755 def __str__(self) -> str:
756 return "when others =>"
759@export
760class CaseGenerateStatement(GenerateStatement):
761 """
762 Represents a case...generate statement.
764 .. admonition:: Example
766 .. code-block:: VHDL
768 gen: case selector generate
769 case choice1 =>
770 -- ...
771 case choice2 =>
772 -- ...
773 case others =>
774 -- ...
775 end generate;
776 """
778 _expression: ExpressionUnion
779 _cases: List[GenerateCase]
781 def __init__(
782 self,
783 label: str,
784 expression: ExpressionUnion,
785 cases: Iterable[ConcurrentCase],
786 allowBlackbox: Nullable[bool] = None,
787 parent: Nullable[ModelEntity] = None
788 ) -> None:
789 super().__init__(label, allowBlackbox, parent)
791 self._expression = expression
792 expression.Parent = self
794 # TODO: create a mixin for things with cases
795 self._cases = []
796 if cases is not None:
797 for case in cases:
798 self._cases.append(case)
799 case.Parent = self
801 @GenerateStatement.Parent.setter
802 def Parent(self, parent: ModelEntity) -> None:
803 GenerateStatement.Parent.fset(self, parent)
805 # Connect namespaces
806 for case in self._cases:
807 case._namespace.ParentNamespace = parent._namespace
809 @property
810 def SelectExpression(self) -> ExpressionUnion:
811 return self._expression
813 @property
814 def Cases(self) -> List[GenerateCase]:
815 return self._cases
817 def IterateInstantiations(self) -> Generator[Instantiation, None, None]:
818 for case in self._cases:
819 yield from case.IterateInstantiations()
821 def IndexStatement(self) -> None:
822 for case in self._cases:
823 case.IndexStatements()
826@export
827class ForGenerateStatement(GenerateStatement, ConcurrentDeclarationRegionMixin, ConcurrentStatementsMixin):
828 """
829 Represents a for...generate statement.
831 .. admonition:: Example
833 .. code-block:: VHDL
835 gen: for i in 0 to 3 generate
836 -- ...
837 end generate;
838 """
840 _loopIndex: str
841 _range: Range
843 _namespace: Namespace
845 def __init__(
846 self,
847 label: str,
848 loopIndex: str,
849 rng: Range,
850 declaredItems: Nullable[Iterable] = None,
851 statements: Nullable[Iterable[ConcurrentStatement]] = None,
852 allowBlackbox: Nullable[bool] = None,
853 parent: Nullable[ModelEntity] = None
854 ) -> None:
855 super().__init__(label, allowBlackbox, parent)
857 self._namespace = Namespace(self._normalizedLabel)
858 if parent is not None:
859 self._namespace.ParentNamespace = parent._namespace
861 ConcurrentDeclarationRegionMixin.__init__(self, declaredItems)
862 ConcurrentStatementsMixin.__init__(self, statements)
864 self._loopIndex = loopIndex
866 self._range = rng
867 rng.Parent = self
869 @GenerateStatement.Parent.setter
870 def Parent(self, parent: ModelEntity) -> None:
871 GenerateStatement.Parent.fset(self, parent)
873 self._namespace.ParentNamespace = parent._namespace
875 @property
876 def LoopIndex(self) -> str:
877 return self._loopIndex
879 @property
880 def Range(self) -> Range:
881 return self._range
883 # IndexDeclaredItems = ConcurrentStatements.IndexDeclaredItems
885 def IndexStatement(self) -> None:
886 self.IndexStatements()
888 def IndexStatements(self) -> None:
889 super().IndexStatements()
891 def IterateInstantiations(self) -> Generator[Instantiation, None, None]:
892 return ConcurrentStatementsMixin.IterateInstantiations(self)
895@export
896class ConcurrentSignalAssignment(ConcurrentStatement, SignalAssignmentMixin):
897 """
898 A base-class for concurrent signal assignments.
900 .. seealso::
902 * :class:`~pyVHDLModel.Concurrent.ConcurrentSimpleSignalAssignment`
903 * :class:`~pyVHDLModel.Concurrent.ConcurrentSelectedSignalAssignment`
904 * :class:`~pyVHDLModel.Concurrent.ConcurrentConditionalSignalAssignment`
905 """
906 def __init__(self, label: str, target: Name, parent: Nullable[ModelEntity] = None) -> None:
907 super().__init__(label, parent)
908 SignalAssignmentMixin.__init__(self, target)
911@export
912class ConcurrentSimpleSignalAssignment(ConcurrentSignalAssignment):
913 _waveform: List[WaveformElement]
915 def __init__(self, label: str, target: Name, waveform: Iterable[WaveformElement], parent: Nullable[ModelEntity] = None) -> None:
916 super().__init__(label, target, parent)
918 # TODO: extract to mixin
919 self._waveform = []
920 if waveform is not None:
921 for waveformElement in waveform:
922 self._waveform.append(waveformElement)
923 waveformElement.Parent = self
925 @property
926 def Waveform(self) -> List[WaveformElement]:
927 return self._waveform
930@export
931class ConcurrentSelectedSignalAssignment(ConcurrentSignalAssignment):
932 def __init__(self, label: str, target: Name, expression: ExpressionUnion, parent: Nullable[ModelEntity] = None) -> None:
933 super().__init__(label, target, parent)
936@export
937class ConcurrentConditionalSignalAssignment(ConcurrentSignalAssignment):
938 def __init__(self, label: str, target: Name, expression: ExpressionUnion, parent: Nullable[ModelEntity] = None) -> None:
939 super().__init__(label, target, parent)
942@export
943class ConcurrentAssertStatement(ConcurrentStatement, AssertStatementMixin):
944 def __init__(
945 self,
946 condition: ExpressionUnion,
947 message: ExpressionUnion,
948 severity: Nullable[ExpressionUnion] = None,
949 label: Nullable[str] = None,
950 parent: Nullable[ModelEntity] = None
951 ) -> None:
952 super().__init__(label, parent)
953 AssertStatementMixin.__init__(self, condition, message, severity)