Coverage for pyVHDLModel/Concurrent.py: 92%
678 statements
« prev ^ index » next coverage.py v7.17.0, created at 2026-10-25 10:05 +0000
« prev ^ index » next coverage.py v7.17.0, created at 2026-10-25 10:05 +0000
1# ==================================================================================================================== #
2# __ ___ _ ____ _ __ __ _ _ #
3# _ __ _ \ \ / / | | | _ \| | | \/ | ___ __| | ___| | #
4# | '_ \| | | \ \ / /| |_| | | | | | | |\/| |/ _ \ / _` |/ _ \ | #
5# | |_) | |_| |\ V / | _ | |_| | |___| | | | (_) | (_| | __/ | #
6# | .__/ \__, | \_/ |_| |_|____/|_____|_| |_|\___/ \__,_|\___|_| #
7# |_| |___/ #
8# ==================================================================================================================== #
9# Authors: #
10# Patrick Lehmann #
11# #
12# License: #
13# ==================================================================================================================== #
14# Copyright 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 __future__ import annotations
39from typing import TYPE_CHECKING, Union, Iterable, Generator, Optional as Nullable
41from pyTooling.Common import getFullyQualifiedName, getTypeName
42from pyTooling.Decorators import export, readonly
43from pyTooling.MetaClasses import ExtendedType, abstractclass
45from pyVHDLModel.Base import ModelEntity, LabeledEntityMixin, DocumentedEntityMixin, Range, BaseChoice, \
46 BaseCase, IfBranchMixin, ElsifBranchMixin, ElseBranchMixin, AssertStatementMixin, \
47 BlockStatementMixin, WaveformElement, ChoicesMixin
48from pyVHDLModel.Exception import AlreadyInDesignError, DuplicateLabelError, NotAChildError
49from pyVHDLModel.Regions import ConcurrentDeclarationRegionMixin, SequentialDeclarationRegionMixin, \
50 WithGenericsMixin, WithPortsMixin
51from pyVHDLModel.Name import Name
52from pyVHDLModel.Symbol import ComponentInstantiationSymbol, EntityInstantiationSymbol, ArchitectureSymbol, \
53 ConfigurationInstantiationSymbol, Symbol, SignalSymbol
54from pyVHDLModel.Expression import BaseExpression, QualifiedExpression, FunctionCall, TypeConversion, Literal
55from pyVHDLModel.Association import AssociationItem, ParameterAssociationItem, GenericAssociationItem, \
56 PortAssociationItem, GenericMapAspectMixin, PortMapAspectMixin
57from pyVHDLModel.Interface import PortInterfaceItemMixin, GenericInterfaceItemMixin
58from pyVHDLModel.Common import Statement, ProcedureCallMixin, SignalAssignmentMixin, AllowBlackboxMixin, \
59 ConditionalWaveform, SelectedWaveform, ConditionalWaveformsMixin, WaveformMixin, \
60 ExpressionMixin, SelectedWaveformsMixin
61from pyVHDLModel.Sequential import SequentialStatement, SequentialStatementsMixin
63if TYPE_CHECKING: 63 ↛ 64line 63 didn't jump to line 64 because the condition on line 63 was never true
64 from pyVHDLModel.Visitor import Visitor
67ExpressionUnion = Union[
68 BaseExpression,
69 QualifiedExpression,
70 FunctionCall,
71 TypeConversion,
72 # ConstantOrSymbol, TODO: ObjectSymbol
73 Literal,
74]
77@export
78@abstractclass
79class ConcurrentStatement(Statement):
80 """
81 A base-class for all concurrent statements.
83 .. seealso::
85 * :class:`Instantiation <pyVHDLModel.Concurrent.Instantiation>`
86 * :class:`Process statement <pyVHDLModel.Concurrent.ProcessStatement>`
87 * :class:`Concurrent procedure call <pyVHDLModel.Concurrent.ConcurrentProcedureCall>`
88 * :class:`Concurrent block statement <pyVHDLModel.Concurrent.ConcurrentBlockStatement>`
89 * :class:`Generate statement <pyVHDLModel.Concurrent.GenerateStatement>`
90 * :class:`Concurrent signal assignment <pyVHDLModel.Concurrent.ConcurrentSignalAssignment>`
91 * :class:`Concurrent assert statement <pyVHDLModel.Concurrent.ConcurrentAssertStatement>`
92 """
95@export
96class ConcurrentStatementsMixin(metaclass=ExtendedType, mixin=True, expects=("_ClashingDeclarations", )):
97 """
98 A mixin-class for all language constructs supporting concurrent statements.
100 .. seealso::
102 * :class:`Concurrent block statement <pyVHDLModel.Concurrent.ConcurrentBlockStatement>`
103 * :class:`Generate branch <pyVHDLModel.Concurrent.GenerateBranch>`
104 * :class:`Concurrent case <pyVHDLModel.Concurrent.ConcurrentCase>`
105 * :class:`For generate statement <pyVHDLModel.Concurrent.ForGenerateStatement>`
106 * :class:`Entity <pyVHDLModel.DesignUnit.Entity>`
107 * :class:`Architecture <pyVHDLModel.DesignUnit.Architecture>`
109 .. todo:: concurrent declaration region
110 """
112 _statements: list[ConcurrentStatement] #: List of all concurrent statements in this construct.
114 # TODO: add another instantiation class level for entity/configuration/component inst.
115 _instantiations: dict[str, Instantiation] #: All instantiations, indexed by label.
116 _hierarchy: dict[str, Union[ConcurrentBlockStatement, GenerateStatement]] #: All elements creating a hierarchy level (blocks and generates), in declaration order.
117 _areStatementsIndexed: bool #: ``True`` if :meth:`IndexStatements` filled :attr:`_instantiations` and :attr:`_hierarchy`.
119 def __init__(self, statements: Nullable[Iterable[ConcurrentStatement]] = None) -> None:
120 """
121 Initializes concurrent statements.
123 :param statements: List of all concurrent statements in this construct.
124 """
125 self._statements = statementList = []
127 self._instantiations = {}
128 self._hierarchy = {}
129 self._areStatementsIndexed = False
131 if statements is not None:
132 for statement in statements:
133 statementList.append(statement)
134 statement.Parent = self
136 @readonly
137 def Statements(self) -> list[ConcurrentStatement]:
138 """
139 Read-only property to access the statements (:attr:`_statements`).
141 :returns: List of statements.
142 """
143 return self._statements
145 def _VisitStatements(self, visitor: Visitor) -> None:
146 """
147 Walk the concurrent statements in statement order with a visitor.
149 :param visitor: The visitor receiving the events.
150 """
151 for statement in self._statements:
152 statement.Visit(visitor)
154 def _Labels(self) -> tuple[ConcurrentStatement, ...]:
155 """
156 Return the labeled statements, whose labels are declared in this construct's declarative region.
158 A statement nested in a block or generate statement is declared in that statement's declarative region.
160 :returns: Tuple of labeled statements, in statement order.
161 """
162 return tuple(statement for statement in self._statements if statement._normalizedLabel is not None)
164 def IterateInstantiations(self) -> Generator[Instantiation, None, None]:
165 for instance in self._instantiations.values():
166 yield instance
168 for element in self._hierarchy.values():
169 yield from element.IterateInstantiations()
171 # TODO: move into _init__
172 def IndexStatements(self) -> None:
173 """
174 Index the instantiations, blocks and generate statements of this construct, and the statements nested in them.
176 Both lookup tables (:attr:`_instantiations`, :attr:`_hierarchy`) are cleared first, so indexing again yields the
177 same lookup tables. Afterwards, the statement mutators (e.g. :meth:`InsertStatement`) keep them up to date.
178 """
179 self._instantiations.clear()
180 self._hierarchy.clear()
181 for statement in self._statements:
182 self._IndexStatement(statement)
184 self._areStatementsIndexed = True
186 def _IndexStatement(self, statement: ConcurrentStatement) -> None:
187 """
188 Add an instantiation, a block or a generate statement to its lookup table, and index the statements nested in it.
190 :param statement: The concurrent statement of this construct.
191 """
192 if isinstance(statement, (EntityInstantiation, ComponentInstantiation, ConfigurationInstantiation)):
193 self._instantiations[statement._normalizedLabel] = statement
194 elif isinstance(statement, (ForGenerateStatement, IfGenerateStatement, CaseGenerateStatement)):
195 self._hierarchy[statement._normalizedLabel] = statement
196 statement.IndexStatement()
197 elif isinstance(statement, ConcurrentBlockStatement):
198 self._hierarchy[statement._normalizedLabel] = statement
199 statement.IndexStatements()
201 def _UnindexStatement(self, statement: ConcurrentStatement) -> None:
202 """
203 Remove an instantiation, a block or a generate statement from its lookup table.
205 :param statement: The concurrent statement of this construct.
206 """
207 if self._instantiations.get(statement._normalizedLabel) is statement:
208 del self._instantiations[statement._normalizedLabel]
209 elif self._hierarchy.get(statement._normalizedLabel) is statement: 209 ↛ exitline 209 didn't return from function '_UnindexStatement' because the condition on line 209 was always true
210 del self._hierarchy[statement._normalizedLabel]
212 def AddStatement(self, statement: ConcurrentStatement) -> None:
213 """
214 Add a concurrent statement at the end of this construct.
216 The statement's parent is set to this construct. If the statements are indexed, an instantiation, a block or a
217 generate statement is added to the lookup table matching its kind.
219 :param statement: The concurrent statement to add.
220 :raises ValueError: If parameter 'statement' is ``None``.
221 :raises TypeError: If parameter 'statement' is not of type :class:`ConcurrentStatement`.
222 :raises AlreadyInDesignError: If parameter 'statement' already has a parent.
223 :raises DuplicateLabelError: If the declarative region already declares the statement's label.
225 .. seealso::
227 :meth:`InsertStatement`
228 |rarr| Insert a concurrent statement at a position of this construct.
229 :meth:`RemoveStatement`
230 |rarr| Remove a concurrent statement from this construct.
231 """
232 self.InsertStatement(len(self._statements), statement)
234 def InsertStatement(self, index: int, statement: ConcurrentStatement) -> None:
235 """
236 Insert a concurrent statement at a position of this construct.
238 The statement's parent is set to this construct: a process, block or generate statement connects its namespace to
239 this construct's namespace. If the statements are indexed (:meth:`IndexStatements`), an instantiation, a block or
240 a generate statement is added to the lookup table matching its kind, and the statements nested in it are indexed.
242 A statement label is declared in the declarative region of this construct: it may neither repeat another
243 statement's label, nor an identifier declared in the region, including the region an entity shares with its
244 architectures. An unlabeled statement declares nothing.
246 :param index: Position, from ``0`` (first) to the number of statements (append). A negative index
247 counts from the end, as for :meth:`list.insert`: ``-1`` inserts before the last
248 statement.
249 :param statement: The concurrent statement to insert.
250 :raises ValueError: If parameter 'index' is ``None``.
251 :raises TypeError: If parameter 'index' is not of type :class:`int`.
252 :raises ValueError: If parameter 'index' is out of range.
253 :raises ValueError: If parameter 'statement' is ``None``.
254 :raises TypeError: If parameter 'statement' is not of type :class:`ConcurrentStatement`.
255 :raises AlreadyInDesignError: If parameter 'statement' already has a parent.
256 :raises DuplicateLabelError: If the declarative region already declares the statement's label.
258 .. seealso::
260 :meth:`AddStatement`
261 |rarr| Add a concurrent statement at the end of this construct.
262 :meth:`InsertStatementBefore`
263 |rarr| Insert a concurrent statement before another statement.
264 :meth:`InsertStatementAfter`
265 |rarr| Insert a concurrent statement after another statement.
266 :meth:`RemoveStatement`
267 |rarr| Remove a concurrent statement from this construct.
268 :meth:`MoveStatement`
269 |rarr| Move a concurrent statement to a position of this construct.
270 """
271 if index is None:
272 raise ValueError("Parameter 'index' is None.")
273 elif not isinstance(index, int):
274 ex = TypeError("Parameter 'index' is not of type 'int'.")
275 ex.add_note(f"Got type '{getFullyQualifiedName(index)}'.")
276 raise ex
277 elif not (-len(self._statements) <= index <= len(self._statements)):
278 ex = ValueError(f"Parameter 'index' is out of range {-len(self._statements)}..{len(self._statements)}.")
279 ex.add_note(f"Got value '{index}'.")
280 raise ex
282 if statement is None:
283 raise ValueError("Parameter 'statement' is None.")
284 elif not isinstance(statement, ConcurrentStatement):
285 ex = TypeError("Parameter 'statement' is not of type 'ConcurrentStatement'.")
286 ex.add_note(f"Got type '{getFullyQualifiedName(statement)}'.")
287 raise ex
288 elif statement._parent is not None:
289 label = "" if statement._label is None else f" '{statement._label}'"
290 ex = AlreadyInDesignError(
291 f"{getTypeName(statement)}{label} already has a parent.",
292 element=statement,
293 parent=statement._parent
294 )
295 ex.add_note(f"Remove it from its {getTypeName(statement._parent)} first.")
296 raise ex
298 if len(clashes := self._ClashingDeclarations(statement)) > 0:
299 ex = DuplicateLabelError(
300 f"{getTypeName(clashes[0]._parent)} already declares '{statement._label}'.",
301 identifier=statement._label,
302 namespace=self._namespace,
303 element=statement,
304 existing=clashes[0]
305 )
306 ex.add_note(f"Existing declaration is of type '{getFullyQualifiedName(clashes[0])}'.")
307 raise ex
309 self._statements.insert(index, statement)
310 statement.Parent = self
311 if self._areStatementsIndexed:
312 self._IndexStatement(statement)
314 def InsertStatementBefore(self, statement: ConcurrentStatement, before: ConcurrentStatement) -> None:
315 """
316 Insert a concurrent statement before another statement of this construct.
318 The statement's parent is set to this construct. If the statements are indexed, an instantiation, a block or a
319 generate statement is added to the lookup table matching its kind.
321 :param statement: The concurrent statement to insert.
322 :param before: The statement of this construct to insert before.
323 :raises ValueError: If parameter 'before' is ``None``.
324 :raises TypeError: If parameter 'before' is not of type :class:`~pyVHDLModel.Base.ModelEntity`.
325 :raises NotAChildError: If parameter 'before' is not a statement of this construct.
326 :raises ValueError: If parameter 'statement' is ``None``.
327 :raises TypeError: If parameter 'statement' is not of type :class:`ConcurrentStatement`.
328 :raises AlreadyInDesignError: If parameter 'statement' already has a parent.
329 :raises DuplicateLabelError: If the declarative region already declares the statement's label.
331 .. seealso::
333 :meth:`InsertStatement`
334 |rarr| Insert a concurrent statement at a position of this construct.
335 :meth:`InsertStatementAfter`
336 |rarr| Insert a concurrent statement after another statement.
337 """
338 if before is None: 338 ↛ 339line 338 didn't jump to line 339 because the condition on line 338 was never true
339 raise ValueError("Parameter 'before' is None.")
340 elif not isinstance(before, ModelEntity): 340 ↛ 341line 340 didn't jump to line 341 because the condition on line 340 was never true
341 ex = TypeError("Parameter 'before' is not of type 'ModelEntity'.")
342 ex.add_note(f"Got type '{getFullyQualifiedName(before)}'.")
343 raise ex
345 for index, item in enumerate(self._statements):
346 if item is before:
347 break
348 else:
349 label = ""
350 if isinstance(before, LabeledEntityMixin) and before._label is not None: 350 ↛ 352line 350 didn't jump to line 352 because the condition on line 350 was always true
351 label = f" '{before._label}'"
352 raise NotAChildError(
353 f"{getTypeName(before)}{label} is not a statement of this {getTypeName(self)}.",
354 element=before,
355 parent=self
356 )
358 self.InsertStatement(index, statement)
360 def InsertStatementAfter(self, statement: ConcurrentStatement, after: ConcurrentStatement) -> None:
361 """
362 Insert a concurrent statement after another statement of this construct.
364 The statement's parent is set to this construct. If the statements are indexed, an instantiation, a block or a
365 generate statement is added to the lookup table matching its kind.
367 :param statement: The concurrent statement to insert.
368 :param after: The statement of this construct to insert after.
369 :raises ValueError: If parameter 'after' is ``None``.
370 :raises TypeError: If parameter 'after' is not of type :class:`~pyVHDLModel.Base.ModelEntity`.
371 :raises NotAChildError: If parameter 'after' is not a statement of this construct.
372 :raises ValueError: If parameter 'statement' is ``None``.
373 :raises TypeError: If parameter 'statement' is not of type :class:`ConcurrentStatement`.
374 :raises AlreadyInDesignError: If parameter 'statement' already has a parent.
375 :raises DuplicateLabelError: If the declarative region already declares the statement's label.
377 .. seealso::
379 :meth:`InsertStatement`
380 |rarr| Insert a concurrent statement at a position of this construct.
381 :meth:`InsertStatementBefore`
382 |rarr| Insert a concurrent statement before another statement.
383 """
384 if after is None: 384 ↛ 385line 384 didn't jump to line 385 because the condition on line 384 was never true
385 raise ValueError("Parameter 'after' is None.")
386 elif not isinstance(after, ModelEntity): 386 ↛ 387line 386 didn't jump to line 387 because the condition on line 386 was never true
387 ex = TypeError("Parameter 'after' is not of type 'ModelEntity'.")
388 ex.add_note(f"Got type '{getFullyQualifiedName(after)}'.")
389 raise ex
391 for index, item in enumerate(self._statements):
392 if item is after: 392 ↛ 391line 392 didn't jump to line 391 because the condition on line 392 was always true
393 break
394 else:
395 label = ""
396 if isinstance(after, LabeledEntityMixin) and after._label is not None: 396 ↛ 397line 396 didn't jump to line 397 because the condition on line 396 was never true
397 label = f" '{after._label}'"
398 raise NotAChildError(
399 f"{getTypeName(after)}{label} is not a statement of this {getTypeName(self)}.",
400 element=after,
401 parent=self
402 )
404 self.InsertStatement(index + 1, statement)
406 def RemoveStatement(self, statement: ConcurrentStatement) -> None:
407 """
408 Remove a concurrent statement from this construct.
410 The statement is detached: its parent is cleared. If the statements are indexed, an instantiation, a block or a
411 generate statement is removed from its lookup table. The statement itself is unchanged and can be added to another
412 construct, or inserted at another position. A removed process, block or generate statement keeps the link of its
413 namespace to this construct's namespace.
415 :param statement: The concurrent statement to remove.
416 :raises ValueError: If parameter 'statement' is ``None``.
417 :raises TypeError: If parameter 'statement' is not of type :class:`~pyVHDLModel.Base.ModelEntity`.
418 :raises NotAChildError: If parameter 'statement' is not a statement of this construct.
420 .. seealso::
422 :meth:`AddStatement`
423 |rarr| Add a concurrent statement at the end of this construct.
424 :meth:`InsertStatement`
425 |rarr| Insert a concurrent statement at a position of this construct.
426 :meth:`MoveStatement`
427 |rarr| Move a concurrent statement to a position of this construct.
428 """
429 if statement is None:
430 raise ValueError("Parameter 'statement' is None.")
431 elif not isinstance(statement, ModelEntity):
432 ex = TypeError("Parameter 'statement' is not of type 'ModelEntity'.")
433 ex.add_note(f"Got type '{getFullyQualifiedName(statement)}'.")
434 raise ex
436 for index, item in enumerate(self._statements):
437 if item is statement: 437 ↛ 436line 437 didn't jump to line 436 because the condition on line 437 was always true
438 break
439 else:
440 label = ""
441 if isinstance(statement, LabeledEntityMixin) and statement._label is not None: 441 ↛ 443line 441 didn't jump to line 443 because the condition on line 441 was always true
442 label = f" '{statement._label}'"
443 raise NotAChildError(
444 f"{getTypeName(statement)}{label} is not a statement of this {getTypeName(self)}.",
445 element=statement,
446 parent=self
447 )
449 if self._areStatementsIndexed:
450 self._UnindexStatement(statement)
452 del self._statements[index]
453 statement._parent = None
455 def MoveStatement(self, statement: ConcurrentStatement, index: int) -> None:
456 """
457 Move a concurrent statement to a position of this construct.
459 The statement stays a statement of this construct: only the order of the statements changes. If the statements are
460 indexed (:meth:`IndexStatements`), the lookup tables are unchanged.
462 :param statement: The concurrent statement to move.
463 :param index: Position of the statement after the move, from ``0`` (first) to the number of statements
464 minus one (last). A negative index counts from the end, as for a :class:`list` index: ``-1``
465 moves the statement to the end.
466 :raises ValueError: If parameter 'statement' is ``None``.
467 :raises TypeError: If parameter 'statement' is not of type :class:`~pyVHDLModel.Base.ModelEntity`.
468 :raises NotAChildError: If parameter 'statement' is not a statement of this construct.
469 :raises ValueError: If parameter 'index' is ``None``.
470 :raises TypeError: If parameter 'index' is not of type :class:`int`.
471 :raises ValueError: If parameter 'index' is out of range.
473 .. seealso::
475 :meth:`MoveStatementBefore`
476 |rarr| Move a concurrent statement before another statement.
477 :meth:`MoveStatementAfter`
478 |rarr| Move a concurrent statement after another statement.
479 :meth:`InsertStatement`
480 |rarr| Insert a concurrent statement at a position of this construct.
481 :meth:`RemoveStatement`
482 |rarr| Remove a concurrent statement from this construct.
483 """
484 if statement is None: 484 ↛ 485line 484 didn't jump to line 485 because the condition on line 484 was never true
485 raise ValueError("Parameter 'statement' is None.")
486 elif not isinstance(statement, ModelEntity): 486 ↛ 487line 486 didn't jump to line 487 because the condition on line 486 was never true
487 ex = TypeError("Parameter 'statement' is not of type 'ModelEntity'.")
488 ex.add_note(f"Got type '{getFullyQualifiedName(statement)}'.")
489 raise ex
491 for currentIndex, item in enumerate(self._statements):
492 if item is statement:
493 break
494 else:
495 label = ""
496 if isinstance(statement, LabeledEntityMixin) and statement._label is not None: 496 ↛ 498line 496 didn't jump to line 498 because the condition on line 496 was always true
497 label = f" '{statement._label}'"
498 raise NotAChildError(
499 f"{getTypeName(statement)}{label} is not a statement of this {getTypeName(self)}.",
500 element=statement,
501 parent=self
502 )
504 if index is None: 504 ↛ 505line 504 didn't jump to line 505 because the condition on line 504 was never true
505 raise ValueError("Parameter 'index' is None.")
506 elif not isinstance(index, int): 506 ↛ 507line 506 didn't jump to line 507 because the condition on line 506 was never true
507 ex = TypeError("Parameter 'index' is not of type 'int'.")
508 ex.add_note(f"Got type '{getFullyQualifiedName(index)}'.")
509 raise ex
510 elif not (-len(self._statements) <= index < len(self._statements)):
511 ex = ValueError(f"Parameter 'index' is out of range {-len(self._statements)}..{len(self._statements) - 1}.")
512 ex.add_note(f"Got value '{index}'.")
513 raise ex
515 newIndex = index if index >= 0 else len(self._statements) + index
516 del self._statements[currentIndex]
517 self._statements.insert(newIndex, statement)
519 def MoveStatementBefore(self, statement: ConcurrentStatement, before: ConcurrentStatement) -> None:
520 """
521 Move a concurrent statement before another statement of this construct.
523 The statement stays a statement of this construct: only the order of the statements changes, as for
524 :meth:`MoveStatement`. Moving a statement before itself keeps it in place.
526 :param statement: The concurrent statement to move.
527 :param before: The statement of this construct to move before.
528 :raises ValueError: If parameter 'before' is ``None``.
529 :raises TypeError: If parameter 'before' is not of type :class:`~pyVHDLModel.Base.ModelEntity`.
530 :raises NotAChildError: If parameter 'before' is not a statement of this construct.
531 :raises ValueError: If parameter 'statement' is ``None``.
532 :raises TypeError: If parameter 'statement' is not of type :class:`~pyVHDLModel.Base.ModelEntity`.
533 :raises NotAChildError: If parameter 'statement' is not a statement of this construct.
535 .. seealso::
537 :meth:`MoveStatement`
538 |rarr| Move a concurrent statement to a position of this construct.
539 :meth:`MoveStatementAfter`
540 |rarr| Move a concurrent statement after another statement.
541 """
542 if before is None: 542 ↛ 543line 542 didn't jump to line 543 because the condition on line 542 was never true
543 raise ValueError("Parameter 'before' is None.")
544 elif not isinstance(before, ModelEntity): 544 ↛ 545line 544 didn't jump to line 545 because the condition on line 544 was never true
545 ex = TypeError("Parameter 'before' is not of type 'ModelEntity'.")
546 ex.add_note(f"Got type '{getFullyQualifiedName(before)}'.")
547 raise ex
549 for index, item in enumerate(self._statements):
550 if item is before:
551 break
552 else:
553 label = ""
554 if isinstance(before, LabeledEntityMixin) and before._label is not None: 554 ↛ 555line 554 didn't jump to line 555 because the condition on line 554 was never true
555 label = f" '{before._label}'"
556 raise NotAChildError(
557 f"{getTypeName(before)}{label} is not a statement of this {getTypeName(self)}.",
558 element=before,
559 parent=self
560 )
562 precedes = any(item is statement for item in self._statements[:index])
563 self.MoveStatement(statement, index - 1 if precedes else index)
565 def MoveStatementAfter(self, statement: ConcurrentStatement, after: ConcurrentStatement) -> None:
566 """
567 Move a concurrent statement after another statement of this construct.
569 The statement stays a statement of this construct: only the order of the statements changes, as for
570 :meth:`MoveStatement`. Moving a statement after itself keeps it in place.
572 :param statement: The concurrent statement to move.
573 :param after: The statement of this construct to move after.
574 :raises ValueError: If parameter 'after' is ``None``.
575 :raises TypeError: If parameter 'after' is not of type :class:`~pyVHDLModel.Base.ModelEntity`.
576 :raises NotAChildError: If parameter 'after' is not a statement of this construct.
577 :raises ValueError: If parameter 'statement' is ``None``.
578 :raises TypeError: If parameter 'statement' is not of type :class:`~pyVHDLModel.Base.ModelEntity`.
579 :raises NotAChildError: If parameter 'statement' is not a statement of this construct.
581 .. seealso::
583 :meth:`MoveStatement`
584 |rarr| Move a concurrent statement to a position of this construct.
585 :meth:`MoveStatementBefore`
586 |rarr| Move a concurrent statement before another statement.
587 """
588 if after is None: 588 ↛ 589line 588 didn't jump to line 589 because the condition on line 588 was never true
589 raise ValueError("Parameter 'after' is None.")
590 elif not isinstance(after, ModelEntity): 590 ↛ 591line 590 didn't jump to line 591 because the condition on line 590 was never true
591 ex = TypeError("Parameter 'after' is not of type 'ModelEntity'.")
592 ex.add_note(f"Got type '{getFullyQualifiedName(after)}'.")
593 raise ex
595 for index, item in enumerate(self._statements): 595 ↛ 599line 595 didn't jump to line 599 because the loop on line 595 didn't complete
596 if item is after: 596 ↛ 595line 596 didn't jump to line 595 because the condition on line 596 was always true
597 break
598 else:
599 label = ""
600 if isinstance(after, LabeledEntityMixin) and after._label is not None:
601 label = f" '{after._label}'"
602 raise NotAChildError(
603 f"{getTypeName(after)}{label} is not a statement of this {getTypeName(self)}.",
604 element=after,
605 parent=self
606 )
608 precedes = any(item is statement for item in self._statements[:index + 1])
609 self.MoveStatement(statement, index if precedes else index + 1)
612@export
613@abstractclass
614class Instantiation(ConcurrentStatement, GenericMapAspectMixin, PortMapAspectMixin):
615 """
616 A base-class for all (component) instantiations.
618 .. seealso::
620 * :class:`Component instantiation <pyVHDLModel.Concurrent.ComponentInstantiation>`
621 * :class:`Entity instantiation <pyVHDLModel.Concurrent.EntityInstantiation>`
622 * :class:`Configuration instantiation <pyVHDLModel.Concurrent.ConfigurationInstantiation>`
623 """
625 def __init__(
626 self,
627 label: str,
628 genericAssociationItems: Nullable[Iterable[GenericAssociationItem]] = None,
629 portAssociationItems: Nullable[Iterable[PortAssociationItem]] = None,
630 parent: Nullable[ModelEntity] = None
631 ) -> None:
632 """
633 Initializes an instantiation.
635 :param label: The label of a model entity.
636 :param genericAssociationItems: List of all generic associations in the generic map aspect.
637 :param portAssociationItems: List of all port associations in the port map aspect.
638 :param parent: The parent model entity of this entity.
639 """
640 super().__init__(label, parent)
641 GenericMapAspectMixin.__init__(self, genericAssociationItems)
642 PortMapAspectMixin.__init__(self, portAssociationItems)
644 def _VisitMapAspects(self, visitor: Visitor) -> None:
645 """
646 Walk the generic map aspect and the port map aspect of this instantiation with a visitor.
648 :param visitor: The visitor receiving the events.
649 """
650 self._VisitGenericMapAspect(visitor)
651 self._VisitPortMapAspect(visitor)
656@export
657class ComponentInstantiation(Instantiation):
658 """
659 Represents a component instantiation.
661 The instantiated component is available as :data:`Component`, the associations as
662 :data:`GenericAssociationItems` and :data:`PortAssociationItems`. The label is mandatory.
664 .. admonition:: Example
666 .. code-block:: VHDL
668 inst : component Counter;
669 --^^^^ <- Label
670 -- ^^^^^^^ <- Component
671 """
673 _component: ComponentInstantiationSymbol #: Reference to the instantiated component.
675 def __init__(
676 self,
677 label: str,
678 componentSymbol: ComponentInstantiationSymbol,
679 genericAssociationItems: Nullable[Iterable[AssociationItem]] = None,
680 portAssociationItems: Nullable[Iterable[AssociationItem]] = None,
681 parent: Nullable[ModelEntity] = None
682 ) -> None:
683 """
684 Initializes a component instantiation.
686 :param label: The label of a model entity.
687 :param componentSymbol: Reference to the instantiated component.
688 :param genericAssociationItems: List of all generic associations in the generic map aspect.
689 :param portAssociationItems: List of all port associations in the port map aspect.
690 :param parent: The parent model entity of this entity.
691 """
692 super().__init__(label, genericAssociationItems, portAssociationItems, parent)
694 self._component = componentSymbol
695 componentSymbol.Parent = self
697 def Visit(self, visitor: Visitor) -> None:
698 """
699 Walk this component instantiation, its component and its map aspects with a visitor.
701 :param visitor: The visitor receiving the events.
702 """
703 visitor.VisitComponentInstantiation(self)
704 self._component.Visit(visitor)
705 self._VisitMapAspects(visitor)
706 visitor.DepartComponentInstantiation(self)
708 @readonly
709 def Component(self) -> ComponentInstantiationSymbol:
710 """
711 Read-only property to access the component (:attr:`_component`).
713 :returns: The component.
714 """
715 return self._component
718@export
719class EntityInstantiation(Instantiation):
720 """
721 Represents a direct entity instantiation.
723 The instantiated entity is available as :data:`Entity` and the optionally selected architecture
724 as :data:`Architecture`. The label is mandatory.
726 .. admonition:: Example
728 .. code-block:: VHDL
730 inst : entity work.Counter(rtl);
731 --^^^^ <- Label
732 -- ^^^^^^^^^^^^ <- Entity
733 -- ^^^ <- optional Architecture
734 """
736 _entity: EntityInstantiationSymbol #: Reference to the directly instantiated entity.
737 _architecture: ArchitectureSymbol #: Reference to the selected architecture, if one was given.
739 def __init__(
740 self,
741 label: str,
742 entitySymbol: EntityInstantiationSymbol,
743 architectureSymbol: Nullable[ArchitectureSymbol] = None,
744 genericAssociationItems: Nullable[Iterable[AssociationItem]] = None,
745 portAssociationItems: Nullable[Iterable[AssociationItem]] = None,
746 parent: Nullable[ModelEntity] = None
747 ) -> None:
748 """
749 Initializes a direct entity instantiation.
751 :param label: The label of a model entity.
752 :param entitySymbol: Reference to the directly instantiated entity.
753 :param architectureSymbol: Reference to the selected architecture, if one was given.
754 :param genericAssociationItems: List of all generic associations in the generic map aspect.
755 :param portAssociationItems: List of all port associations in the port map aspect.
756 :param parent: The parent model entity of this entity.
757 """
758 super().__init__(label, genericAssociationItems, portAssociationItems, parent)
760 self._entity = entitySymbol
761 entitySymbol.Parent = self
763 self._architecture = architectureSymbol
764 if architectureSymbol is not None:
765 architectureSymbol.Parent = self
767 def Visit(self, visitor: Visitor) -> None:
768 """
769 Walk this entity instantiation, its entity, its architecture (if any) and its map aspects with a visitor.
771 :param visitor: The visitor receiving the events.
772 """
773 visitor.VisitEntityInstantiation(self)
774 self._entity.Visit(visitor)
775 if self._architecture is not None:
776 visitor.VisitLeftParenthesis(self)
777 self._architecture.Visit(visitor)
778 visitor.VisitRightParenthesis(self)
780 self._VisitMapAspects(visitor)
781 visitor.DepartEntityInstantiation(self)
783 @readonly
784 def Entity(self) -> EntityInstantiationSymbol:
785 """
786 Read-only property to access the entity (:attr:`_entity`).
788 :returns: The entity.
789 """
790 return self._entity
792 @readonly
793 def Architecture(self) -> ArchitectureSymbol:
794 """
795 Read-only property to access the architecture (:attr:`_architecture`).
797 :returns: The architecture.
798 """
799 return self._architecture
802@export
803class ConfigurationInstantiation(Instantiation):
804 """
805 Represents a configuration instantiation.
807 The instantiated configuration is available as :data:`Configuration`. The label is mandatory.
809 .. admonition:: Example
811 .. code-block:: VHDL
813 inst : configuration Counter;
814 --^^^^ <- Label
815 -- ^^^^^^^ <- Configuration
816 """
818 _configuration: ConfigurationInstantiationSymbol #: Reference to the instantiated configuration.
820 def __init__(
821 self,
822 label: str,
823 configurationSymbol: ConfigurationInstantiationSymbol,
824 genericAssociationItems: Nullable[Iterable[AssociationItem]] = None,
825 portAssociationItems: Nullable[Iterable[AssociationItem]] = None,
826 parent: Nullable[ModelEntity] = None
827 ) -> None:
828 """
829 Initializes a configuration instantiation.
831 :param label: The label of a model entity.
832 :param configurationSymbol: Reference to the instantiated configuration.
833 :param genericAssociationItems: List of all generic associations in the generic map aspect.
834 :param portAssociationItems: List of all port associations in the port map aspect.
835 :param parent: The parent model entity of this entity.
836 """
837 super().__init__(label, genericAssociationItems, portAssociationItems, parent)
839 self._configuration = configurationSymbol
840 configurationSymbol.Parent = self
842 def Visit(self, visitor: Visitor) -> None:
843 """
844 Walk this configuration instantiation, its configuration and its map aspects with a visitor.
846 :param visitor: The visitor receiving the events.
847 """
848 visitor.VisitConfigurationInstantiation(self)
849 self._configuration.Visit(visitor)
850 self._VisitMapAspects(visitor)
851 visitor.DepartConfigurationInstantiation(self)
853 @readonly
854 def Configuration(self) -> ConfigurationInstantiationSymbol:
855 """
856 Read-only property to access the configuration (:attr:`_configuration`).
858 :returns: The configuration.
859 """
860 return self._configuration
863@export
864class ProcessStatement(ConcurrentStatement, SequentialDeclarationRegionMixin, SequentialStatementsMixin, DocumentedEntityMixin):
865 """
866 Represents a process statement.
868 A process declares its own items (:data:`DeclaredItems`) and groups sequential statements
869 (:data:`Statements`). It may name a sensitivity list (:data:`SensitivityList`).
871 .. admonition:: Example
873 .. code-block:: VHDL
875 proc : process (clock)
876 --^^^^ <- optional Label
877 -- ^^^^^ <- optional SensitivityList
878 variable v : bit;
879 -- ^^^^^^^^^^^^^^^^^ <- DeclaredItems
880 begin
881 v := '1';
882 -- ^^^^^^^^^ <- Statements
883 end process;
884 """
886 # TODO: implement a SignalSymbol
887 _sensitivityList: list[Name] #: List of all signal names in the sensitivity list, or ``None`` if none was given.
889 def __init__(
890 self,
891 label: Nullable[str] = None,
892 declaredItems: Nullable[Iterable] = None,
893 statements: Nullable[Iterable[SequentialStatement]] = None,
894 sensitivityList: Nullable[Iterable[Name]] = None,
895 documentation: Nullable[str] = None,
896 parent: Nullable[ModelEntity] = None
897 ) -> None:
898 """
899 Initializes a process statement.
901 :param label: The label of a model entity.
902 :param declaredItems: List of all declared items in this sequential declaration region.
903 :param statements: List of all sequential statements in this construct.
904 :param sensitivityList: List of all signal names in the sensitivity list, or ``None`` if none was given.
905 :param documentation: The documentation comment associated with this declaration.
906 :param parent: The parent model entity of this entity.
907 """
908 super().__init__(label, parent)
909 SequentialDeclarationRegionMixin.__init__(self, self._normalizedLabel, declaredItems)
910 SequentialStatementsMixin.__init__(self, statements)
911 DocumentedEntityMixin.__init__(self, documentation)
913 if sensitivityList is None:
914 self._sensitivityList = None
915 else:
916 self._sensitivityList = signalSymbols = [] # TODO: convert to dict
917 for signalSymbol in sensitivityList:
918 signalSymbols.append(signalSymbol)
919 # signalSymbol._parent = self # FIXME: currently str are provided
921 def Visit(self, visitor: Visitor) -> None:
922 """
923 Walk this process, its sensitivity list (if any), its declared items and its statements with a visitor.
925 :param visitor: The visitor receiving the events.
926 """
927 visitor.VisitProcessStatement(self)
928 if self._sensitivityList is not None:
929 visitor.VisitSensitivityList(self)
930 for index, name in enumerate(self._sensitivityList):
931 if index > 0:
932 visitor.VisitComma(self)
934 name.Visit(visitor)
936 visitor.DepartSensitivityList(self)
938 visitor.VisitIs(self)
939 self._VisitDeclaredItems(visitor)
940 visitor.VisitBegin(self)
941 self._VisitStatements(visitor)
942 visitor.DepartProcessStatement(self)
944 @ConcurrentStatement.Parent.setter
945 def Parent(self, parent: ModelEntity) -> None:
946 ConcurrentStatement.Parent.fset(self, parent)
948 # Connect the process' namespace to the enclosing declaration region's namespace, so a declaration
949 # inside the process hides a same-named one from the architecture, block or generate around it.
950 self._namespace.ParentNamespace = parent._namespace
952 def _LabelRegion(self) -> ProcessStatement:
953 """
954 Return the process, whose declarative region declares the labels of its statements.
956 :returns: The process itself.
957 """
958 return self
960 @readonly
961 def SensitivityList(self) -> list[Name]:
962 """
963 Read-only property to access the sensitivity list (:attr:`_sensitivityList`).
965 :returns: List of sensitivity list.
966 """
967 return self._sensitivityList
970@export
971class ConcurrentProcedureCall(ConcurrentStatement, ProcedureCallMixin):
972 """
973 Represents a concurrent procedure call.
975 Like every concurrent statement, it can carry an optional label (:data:`Label`).
977 .. admonition:: Example
979 .. code-block:: VHDL
981 proc_lbl : proc(clock, open);
982 --^^^^^^^^ <- optional Label
983 -- ^^^^^^^^^^^^^^^^^ <- the call
985 .. seealso::
987 * :class:`Sequential counterpart <pyVHDLModel.Sequential.SequentialProcedureCall>`
988 """
989 def __init__(
990 self,
991 label: Nullable[str],
992 procedureName: Symbol,
993 parameterAssociationItems: Nullable[Iterable[ParameterAssociationItem]] = None,
994 parent: Nullable[ModelEntity] = None
995 ) -> None:
996 """
997 Initializes a concurrent procedure call.
999 :param label: The label of a model entity.
1000 :param procedureName: Reference to the called procedure.
1001 :param parameterAssociationItems: List of all parameter associations of the call.
1002 :param parent: The parent model entity of this entity.
1003 """
1004 super().__init__(label, parent)
1005 ProcedureCallMixin.__init__(self, procedureName, parameterAssociationItems)
1007 def Visit(self, visitor: Visitor) -> None:
1008 """
1009 Walk this concurrent procedure call, its procedure and its parameters with a visitor.
1011 :param visitor: The visitor receiving the events.
1012 """
1013 visitor.VisitConcurrentProcedureCall(self)
1014 self._VisitProcedureCall(visitor)
1015 visitor.DepartConcurrentProcedureCall(self)
1018@export
1019class ConcurrentBlockStatement(
1020 ConcurrentStatement,
1021 BlockStatementMixin,
1022 LabeledEntityMixin,
1023 WithGenericsMixin,
1024 WithPortsMixin,
1025 GenericMapAspectMixin,
1026 PortMapAspectMixin,
1027 ConcurrentDeclarationRegionMixin,
1028 ConcurrentStatementsMixin,
1029 DocumentedEntityMixin,
1030 AllowBlackboxMixin
1031):
1032 """
1033 Represents a block statement.
1035 A block groups concurrent statements (:data:`Statements`) and may declare its own items
1036 (:data:`DeclaredItems`). It always forms a hierarchy level; independently of that, it may also have
1037 a block header: a generic clause (:data:`GenericItems`) with its generic map aspect
1038 (:data:`GenericAssociationItems`), and a port clause (:data:`PortItems`) with its port map aspect
1039 (:data:`PortAssociationItems`).
1041 .. admonition:: Example
1043 .. code-block:: VHDL
1045 blk : block
1046 --^^^ <- Label
1047 generic (G : positive := 1);
1048 -- ^^^^^^^^^^^^^^^^^^ <- GenericItems
1049 generic map (G => 2);
1050 -- ^^^^^^^^ <- GenericAssociationItems
1051 port (bp : in bit);
1052 -- ^^^^^^^^^^^ <- PortItems
1053 port map (bp => clock);
1054 -- ^^^^^^^^^^^^ <- PortAssociationItems
1055 signal inner : bit := '0';
1056 -- ^^^^^^^^^^^^^^^^^^^^^^^^^^ <- DeclaredItems
1057 begin
1058 inner <= bp;
1059 -- ^^^^^^^^^^^^ <- Statements
1060 end block;
1062 .. seealso::
1064 * :class:`Generate statement <pyVHDLModel.Concurrent.GenerateStatement>`
1065 """
1066 def __init__(
1067 self,
1068 label: str,
1069 genericItems: Nullable[Iterable[GenericInterfaceItemMixin]] = None,
1070 genericAssociationItems: Nullable[Iterable[GenericAssociationItem]] = None,
1071 portItems: Nullable[Iterable[PortInterfaceItemMixin]] = None,
1072 portAssociationItems: Nullable[Iterable[PortAssociationItem]] = None,
1073 declaredItems: Nullable[Iterable] = None,
1074 statements: Iterable[ConcurrentStatement] = None,
1075 documentation: Nullable[str] = None,
1076 allowBlackbox: Nullable[bool] = None,
1077 parent: Nullable[ModelEntity] = None
1078 ) -> None:
1079 """
1080 Initializes a block statement.
1082 :param label: The label of a model entity.
1083 :param genericItems: List of all generics, in declaration order.
1084 :param genericAssociationItems: List of all generic associations in the generic map aspect.
1085 :param portItems: List of all ports, in declaration order.
1086 :param portAssociationItems: List of all port associations in the port map aspect.
1087 :param declaredItems: List of all declared items in this concurrent declaration region.
1088 :param statements: List of all concurrent statements in this construct.
1089 :param documentation: The documentation comment associated with this declaration.
1090 :param allowBlackbox: Allow blackboxes for components in language entity.
1091 :param parent: The parent model entity of this entity.
1092 """
1093 super().__init__(label, parent)
1095 BlockStatementMixin.__init__(self)
1096 LabeledEntityMixin.__init__(self, label)
1097 ConcurrentDeclarationRegionMixin.__init__(self, self._normalizedLabel, declaredItems)
1098 if parent is not None: 1098 ↛ 1099line 1098 didn't jump to line 1099 because the condition on line 1098 was never true
1099 self._namespace.ParentNamespace = parent._namespace
1101 WithGenericsMixin.__init__(self, genericItems)
1102 WithPortsMixin.__init__(self, portItems)
1103 GenericMapAspectMixin.__init__(self, genericAssociationItems)
1104 PortMapAspectMixin.__init__(self, portAssociationItems)
1105 ConcurrentStatementsMixin.__init__(self, statements)
1106 DocumentedEntityMixin.__init__(self, documentation)
1107 AllowBlackboxMixin.__init__(self, allowBlackbox)
1109 def Visit(self, visitor: Visitor) -> None:
1110 """
1111 Walk this block, its block header, its declared items and its statements with a visitor.
1113 :param visitor: The visitor receiving the events.
1114 """
1115 visitor.VisitConcurrentBlockStatement(self)
1116 self._VisitGenericClause(visitor)
1117 self._VisitGenericMapAspect(visitor)
1118 self._VisitPortClause(visitor)
1119 self._VisitPortMapAspect(visitor)
1120 self._VisitDeclaredItems(visitor)
1121 visitor.VisitBegin(self)
1122 self._VisitStatements(visitor)
1123 visitor.DepartConcurrentBlockStatement(self)
1125 @ConcurrentStatement.Parent.setter
1126 def Parent(self, parent: ModelEntity) -> None:
1127 ConcurrentStatement.Parent.fset(self, parent)
1129 self._namespace.ParentNamespace = parent._namespace
1132 def IndexDeclaredItems(self) -> None:
1133 """
1134 A block's ports share the declarative region of its declarative part.
1136 :raises UnhandledCriticalWarningError: If an identifier is declared twice in a declarative region and no
1137 :class:`~pyTooling.Warning.WarningCollector` collects the
1138 :exc:`~pyVHDLModel.Exception.DuplicateDeclarationWarning`.
1139 """
1140 self._IndexPortItems()
1142 super().IndexDeclaredItems()
1144 def _Declarations(self) -> tuple[ModelEntity, ...]:
1145 """
1146 Return all declarations of this block: its generics and ports share the declarative region.
1148 :returns: Tuple of declarations: the generics, the ports, then the declared items.
1149 """
1150 return (*self._genericItems, *self._portItems, *super()._Declarations())
1153@export
1154@abstractclass
1155class GenerateBranch(ModelEntity, ConcurrentDeclarationRegionMixin, ConcurrentStatementsMixin, AllowBlackboxMixin):
1156 """
1157 A base-class for all branches in a generate statements.
1159 .. seealso::
1161 * :class:`If generate branch <pyVHDLModel.Concurrent.IfGenerateBranch>`
1162 * :class:`Elsif generate branch <pyVHDLModel.Concurrent.ElsifGenerateBranch>`
1163 * :class:`Else generate branch <pyVHDLModel.Concurrent.ElseGenerateBranch>`
1164 """
1166 _alternativeLabel: Nullable[str] #: The branch's alternative label, if one was given.
1167 _normalizedAlternativeLabel: Nullable[str] #: The normalized (lower case) alternative label.
1169 def __init__(
1170 self,
1171 declaredItems: Nullable[Iterable] = None,
1172 statements: Nullable[Iterable[ConcurrentStatement]] = None,
1173 alternativeLabel: Nullable[str] = None,
1174 allowBlackbox: Nullable[bool] = None,
1175 parent: Nullable[ModelEntity] = None
1176 ) -> None:
1177 """
1178 Initializes a generate branch.
1180 :param declaredItems: List of all declared items in this concurrent declaration region.
1181 :param statements: List of all concurrent statements in this construct.
1182 :param alternativeLabel: The branch's alternative label, if one was given.
1183 :param allowBlackbox: Allow blackboxes for components in language entity.
1184 :param parent: The parent model entity of this entity.
1185 """
1186 super().__init__(parent)
1188 self._alternativeLabel = alternativeLabel
1189 self._normalizedAlternativeLabel = alternativeLabel.lower() if alternativeLabel is not None else None
1191 ConcurrentDeclarationRegionMixin.__init__(self, self._normalizedAlternativeLabel, declaredItems)
1192 if parent is not None: 1192 ↛ 1193line 1192 didn't jump to line 1193 because the condition on line 1192 was never true
1193 self._namespace.ParentNamespace = parent._namespace
1195 ConcurrentStatementsMixin.__init__(self, statements)
1196 AllowBlackboxMixin.__init__(self, allowBlackbox)
1198 @readonly
1199 def AlternativeLabel(self) -> Nullable[str]:
1200 """
1201 Read-only property to access the alternative label (:attr:`_alternativeLabel`).
1203 :returns: The alternative label, or ``None`` if not set.
1204 """
1205 return self._alternativeLabel
1207 @readonly
1208 def NormalizedAlternativeLabel(self) -> Nullable[str]:
1209 """
1210 Read-only property to access the normalized alternative label (:attr:`_normalizedAlternativeLabel`).
1212 :returns: The normalized alternative label, or ``None`` if not set.
1213 """
1214 return self._normalizedAlternativeLabel
1217@export
1218class IfGenerateBranch(GenerateBranch, IfBranchMixin):
1219 """
1220 Represents if-generate branch in a generate statement with a concurrent declaration region and concurrent statements.
1222 .. admonition:: Example
1224 .. code-block:: VHDL
1226 gen: if condition generate
1227 -- concurrent declarations
1228 begin
1229 -- concurrent statements
1230 elsif condition generate
1231 -- ...
1232 else generate
1233 -- ...
1234 end generate;
1235 """
1237 def __init__(
1238 self,
1239 condition: ExpressionUnion,
1240 declaredItems: Nullable[Iterable] = None,
1241 statements: Nullable[Iterable[ConcurrentStatement]] = None,
1242 alternativeLabel: Nullable[str] = None,
1243 allowBlackbox: Nullable[bool] = None,
1244 parent: Nullable[ModelEntity] = None
1245 ) -> None:
1246 """
1247 Initializes an if generate branch.
1249 :param condition: The condition guarding this statement.
1250 :param declaredItems: List of all declared items in this concurrent declaration region.
1251 :param statements: List of all concurrent statements in this construct.
1252 :param alternativeLabel: The branch's alternative label, if one was given.
1253 :param allowBlackbox: Allow blackboxes for components in language entity.
1254 :param parent: The parent model entity of this entity.
1255 """
1256 super().__init__(declaredItems, statements, alternativeLabel, allowBlackbox, parent)
1257 IfBranchMixin.__init__(self, condition)
1259 def Visit(self, visitor: Visitor) -> None:
1260 """
1261 Walk this if-generate branch, its condition, its declared items and its statements with a visitor.
1263 :param visitor: The visitor receiving the events.
1264 """
1265 visitor.VisitIfGenerateBranch(self)
1266 self._condition.Visit(visitor)
1267 visitor.VisitGenerate(self)
1268 self._VisitDeclaredItems(visitor)
1269 visitor.VisitBegin(self)
1270 self._VisitStatements(visitor)
1271 visitor.DepartIfGenerateBranch(self)
1274@export
1275class ElsifGenerateBranch(GenerateBranch, ElsifBranchMixin):
1276 """
1277 Represents elsif-generate branch in a generate statement with a concurrent declaration region and concurrent statements.
1279 .. admonition:: Example
1281 .. code-block:: VHDL
1283 gen: if condition generate
1284 -- ...
1285 elsif condition generate
1286 -- concurrent declarations
1287 begin
1288 -- concurrent statements
1289 else generate
1290 -- ...
1291 end generate;
1292 """
1294 def __init__(
1295 self,
1296 condition: ExpressionUnion,
1297 declaredItems: Nullable[Iterable] = None,
1298 statements: Nullable[Iterable[ConcurrentStatement]] = None,
1299 alternativeLabel: Nullable[str] = None,
1300 allowBlackbox: Nullable[bool] = None,
1301 parent: Nullable[ModelEntity] = None
1302 ) -> None:
1303 """
1304 Initializes an elsif generate branch.
1306 :param condition: The condition guarding this statement.
1307 :param declaredItems: List of all declared items in this concurrent declaration region.
1308 :param statements: List of all concurrent statements in this construct.
1309 :param alternativeLabel: The branch's alternative label, if one was given.
1310 :param allowBlackbox: Allow blackboxes for components in language entity.
1311 :param parent: The parent model entity of this entity.
1312 """
1313 super().__init__(declaredItems, statements, alternativeLabel, allowBlackbox, parent)
1314 ElsifBranchMixin.__init__(self, condition)
1316 def Visit(self, visitor: Visitor) -> None:
1317 """
1318 Walk this elsif-generate branch, its condition, its declared items and its statements with a visitor.
1320 :param visitor: The visitor receiving the events.
1321 """
1322 visitor.VisitElsifGenerateBranch(self)
1323 self._condition.Visit(visitor)
1324 visitor.VisitGenerate(self)
1325 self._VisitDeclaredItems(visitor)
1326 visitor.VisitBegin(self)
1327 self._VisitStatements(visitor)
1328 visitor.DepartElsifGenerateBranch(self)
1331@export
1332class ElseGenerateBranch(GenerateBranch, ElseBranchMixin):
1333 """
1334 Represents else-generate branch in a generate statement with a concurrent declaration region and concurrent statements.
1336 .. admonition:: Example
1338 .. code-block:: VHDL
1340 gen: if condition generate
1341 -- ...
1342 elsif condition generate
1343 -- ...
1344 else generate
1345 -- concurrent declarations
1346 begin
1347 -- concurrent statements
1348 end generate;
1349 """
1351 def __init__(
1352 self,
1353 declaredItems: Nullable[Iterable] = None,
1354 statements: Nullable[Iterable[ConcurrentStatement]] = None,
1355 alternativeLabel: Nullable[str] = None,
1356 allowBlackbox: Nullable[bool] = None,
1357 parent: Nullable[ModelEntity] = None
1358 ) -> None:
1359 """
1360 Initializes an else generate branch.
1362 :param declaredItems: List of all declared items in this concurrent declaration region.
1363 :param statements: List of all concurrent statements in this construct.
1364 :param alternativeLabel: The branch's alternative label, if one was given.
1365 :param allowBlackbox: Allow blackboxes for components in language entity.
1366 :param parent: The parent model entity of this entity.
1367 """
1368 super().__init__(declaredItems, statements, alternativeLabel, allowBlackbox, parent)
1369 ElseBranchMixin.__init__(self)
1371 def Visit(self, visitor: Visitor) -> None:
1372 """
1373 Walk this else-generate branch, its declared items and its statements with a visitor.
1375 :param visitor: The visitor receiving the events.
1376 """
1377 visitor.VisitElseGenerateBranch(self)
1378 visitor.VisitGenerate(self)
1379 self._VisitDeclaredItems(visitor)
1380 visitor.VisitBegin(self)
1381 self._VisitStatements(visitor)
1382 visitor.DepartElseGenerateBranch(self)
1385@export
1386@abstractclass
1387class GenerateStatement(ConcurrentStatement, AllowBlackboxMixin):
1388 """
1389 Represents the base-class of all generate statements.
1391 A generate statement replicates or conditionally elaborates concurrent statements.
1393 .. seealso::
1395 * :class:`If generate statement <pyVHDLModel.Concurrent.IfGenerateStatement>`
1396 * :class:`Case generate statement <pyVHDLModel.Concurrent.CaseGenerateStatement>`
1397 * :class:`For generate statement <pyVHDLModel.Concurrent.ForGenerateStatement>`
1398 """
1400 def __init__(
1401 self,
1402 label: Nullable[str] = None,
1403 allowBlackbox: Nullable[bool] = None,
1404 parent: Nullable[ModelEntity] = None
1405 ) -> None:
1406 """
1407 Initializes a generate statement.
1409 :param label: The label of a model entity.
1410 :param allowBlackbox: Allow blackboxes for components in language entity.
1411 :param parent: The parent model entity of this entity.
1412 """
1413 super().__init__(label, parent)
1414 AllowBlackboxMixin.__init__(self, allowBlackbox)
1416 # @mustoverride
1417 def IterateInstantiations(self) -> Generator[Instantiation, None, None]:
1418 raise NotImplementedError()
1420 # @mustoverride
1421 def IndexStatement(self) -> None:
1422 raise NotImplementedError()
1425@export
1426class IfGenerateStatement(GenerateStatement):
1427 """
1428 Represents an if-generate statement.
1430 It has one ``if`` branch (:data:`IfBranch`), any number of ``elsif`` branches
1431 (:data:`ElsifBranches`) and an optional ``else`` branch (:data:`ElseBranch`). The label is
1432 mandatory and the branch conditions must be static expressions.
1434 .. admonition:: Example
1436 .. code-block:: VHDL
1438 gen : if WIDTH > 8 generate
1439 --^^^ <- Label
1440 -- ^^^^^^^^^^^^^^^^^^^^^ <- IfBranch
1441 q <= '0';
1442 elsif WIDTH > 4 generate
1443 --^^^^^^^^^^^^^^^^^^^^^^^^ <- ElsifBranches[0]
1444 q <= '1';
1445 else generate
1446 --^^^^^^^^^^^^^ <- ElseBranch
1447 q <= 'Z';
1448 end generate;
1450 .. seealso::
1452 * :class:`Generate branch <pyVHDLModel.Concurrent.GenerateBranch>` base-class
1453 * :class:`If-generate branch <pyVHDLModel.Concurrent.IfGenerateBranch>`
1454 * :class:`Elsif-generate branch <pyVHDLModel.Concurrent.ElsifGenerateBranch>`
1455 * :class:`Else-generate branch <pyVHDLModel.Concurrent.ElseGenerateBranch>`
1456 * :class:`Case-generate statement <pyVHDLModel.Concurrent.CaseGenerateStatement>`
1457 * :class:`For-generate statement <pyVHDLModel.Concurrent.ForGenerateStatement>`
1458 """
1460 _ifBranch: IfGenerateBranch #: The mandatory ``if`` branch.
1461 _elsifBranches: list[ElsifGenerateBranch] #: List of all ``elsif`` branches, in the order they were written.
1462 _elseBranch: Nullable[ElseGenerateBranch] #: The optional ``else`` branch, or ``None`` if none was given.
1464 def __init__(
1465 self,
1466 label: str,
1467 ifBranch: IfGenerateBranch,
1468 elsifBranches: Nullable[Iterable[ElsifGenerateBranch]] = None,
1469 elseBranch: Nullable[ElseGenerateBranch] = None,
1470 allowBlackbox: Nullable[bool] = None,
1471 parent: Nullable[ModelEntity] = None
1472 ) -> None:
1473 """
1474 Initializes an if-generate statement.
1476 :param label: The label of a model entity.
1477 :param ifBranch: The mandatory ``if`` branch.
1478 :param elsifBranches: List of all ``elsif`` branches, in the order they were written.
1479 :param elseBranch: The optional ``else`` branch, or ``None`` if none was given.
1480 :param allowBlackbox: Allow blackboxes for components in language entity.
1481 :param parent: The parent model entity of this entity.
1482 """
1483 super().__init__(label, allowBlackbox, parent)
1485 self._ifBranch = ifBranch
1486 ifBranch.Parent = self
1488 self._elsifBranches = elsifBranchList = []
1489 if elsifBranches is not None:
1490 for branch in elsifBranches:
1491 elsifBranchList.append(branch)
1492 branch.Parent = self
1494 if elseBranch is not None:
1495 self._elseBranch = elseBranch
1496 elseBranch.Parent = self
1497 else:
1498 self._elseBranch = None
1500 def Visit(self, visitor: Visitor) -> None:
1501 """
1502 Walk this if-generate statement and its branches with a visitor.
1504 :param visitor: The visitor receiving the events.
1505 """
1506 visitor.VisitIfGenerateStatement(self)
1507 self._ifBranch.Visit(visitor)
1508 for branch in self._elsifBranches:
1509 branch.Visit(visitor)
1511 if self._elseBranch is not None: 1511 ↛ 1514line 1511 didn't jump to line 1514 because the condition on line 1511 was always true
1512 self._elseBranch.Visit(visitor)
1514 visitor.DepartIfGenerateStatement(self)
1516 @GenerateStatement.Parent.setter
1517 def Parent(self, parent: ModelEntity) -> None:
1518 GenerateStatement.Parent.fset(self, parent)
1520 # Connect namespaces
1521 namespace = self._ifBranch._namespace
1522 namespace.ParentNamespace = parent._namespace
1523 if namespace._name is None: 1523 ↛ 1526line 1523 didn't jump to line 1526 because the condition on line 1523 was always true
1524 namespace._name = self._normalizedLabel
1526 for elseBranch in self._elsifBranches:
1527 elseBranch._namespace.ParentNamespace = parent._namespace
1529 if self._elseBranch is not None: 1529 ↛ exitline 1529 didn't return from function 'Parent' because the condition on line 1529 was always true
1530 self._elseBranch._namespace.ParentNamespace = parent._namespace
1532 @readonly
1533 def IfBranch(self) -> IfGenerateBranch:
1534 """
1535 Read-only property to access the if branch (:attr:`_ifBranch`).
1537 :returns: The if branch.
1538 """
1539 return self._ifBranch
1541 @readonly
1542 def ElsifBranches(self) -> list[ElsifGenerateBranch]:
1543 """
1544 Read-only property to access the elsif branches (:attr:`_elsifBranches`).
1546 :returns: List of elsif branches.
1547 """
1548 return self._elsifBranches
1550 @readonly
1551 def ElseBranch(self) -> Nullable[ElseGenerateBranch]:
1552 """
1553 Read-only property to access the else branch (:attr:`_elseBranch`).
1555 :returns: The else branch, or ``None`` if not set.
1556 """
1557 return self._elseBranch
1559 def IterateInstantiations(self) -> Generator[Instantiation, None, None]:
1560 yield from self._ifBranch.IterateInstantiations()
1561 for branch in self._elsifBranches:
1562 yield from branch.IterateInstantiations()
1563 if self._elseBranch is not None:
1564 yield from self._elseBranch.IterateInstantiations()
1566 def IndexStatement(self) -> None:
1567 self._ifBranch.IndexStatements()
1568 for branch in self._elsifBranches:
1569 branch.IndexStatements()
1570 if self._elseBranch is not None:
1571 self._elseBranch.IndexStatements()
1574@export
1575@abstractclass
1576class ConcurrentChoice(BaseChoice):
1577 """
1578 A base-class for all concurrent choices (in case...generate statements).
1580 .. seealso::
1582 * :class:`Indexed generate choice <pyVHDLModel.Concurrent.IndexedGenerateChoice>`
1583 * :class:`Ranged generate choice <pyVHDLModel.Concurrent.RangedGenerateChoice>`
1584 """
1587@export
1588class IndexedGenerateChoice(ConcurrentChoice):
1589 """
1590 Represents a case-generate choice given by a single value.
1592 The value is available as :data:`Expression`.
1594 .. admonition:: Example
1596 .. code-block:: VHDL
1598 when 8 =>
1599 -- ^ <- Expression
1600 """
1601 _expression: ExpressionUnion #: The expression this choice selects on.
1603 def __init__(self, expression: ExpressionUnion, parent: Nullable[ModelEntity] = None) -> None:
1604 """
1605 Initializes a case-generate choice given by a single value.
1607 :param expression: The expression this choice selects on.
1608 :param parent: The parent model entity of this entity.
1609 """
1610 super().__init__(parent)
1612 self._expression = expression
1613 expression.Parent = self
1615 def Visit(self, visitor: Visitor) -> None:
1616 """
1617 Walk this case-generate choice and its value with a visitor.
1619 :param visitor: The visitor receiving the events.
1620 """
1621 visitor.VisitIndexedGenerateChoice(self)
1622 self._expression.Visit(visitor)
1623 visitor.DepartIndexedGenerateChoice(self)
1625 @readonly
1626 def Expression(self) -> ExpressionUnion:
1627 """
1628 Read-only property to access the expression (:attr:`_expression`).
1630 :returns: The expression.
1631 """
1632 return self._expression
1634 def __str__(self) -> str:
1635 """
1636 Formats the indexed case-generate choice.
1638 **Format:** ``0``
1640 :returns: Formatted indexed case-generate choice.
1641 """
1642 return str(self._expression)
1645@export
1646class RangedGenerateChoice(ConcurrentChoice):
1647 """
1648 Represents a case-generate choice given by a range.
1650 The range is available as :data:`Range`.
1652 .. admonition:: Example
1654 .. code-block:: VHDL
1656 when 0 to 3 =>
1657 -- ^^^^^^ <- Range
1658 """
1659 _range: Range #: The range this choice selects on.
1661 def __init__(self, rng: Range, parent: Nullable[ModelEntity] = None) -> None:
1662 """
1663 Initializes a case-generate choice given by a range.
1665 :param rng: The range this choice selects on.
1666 :param parent: The parent model entity of this entity.
1667 """
1668 super().__init__(parent)
1670 self._range = rng
1671 rng.Parent = self
1673 def Visit(self, visitor: Visitor) -> None:
1674 """
1675 Walk this case-generate choice and its range with a visitor.
1677 :param visitor: The visitor receiving the events.
1678 """
1679 visitor.VisitRangedGenerateChoice(self)
1680 self._range.Visit(visitor)
1681 visitor.DepartRangedGenerateChoice(self)
1683 @readonly
1684 def Range(self) -> Range:
1685 """
1686 Read-only property to access the range (:attr:`_range`).
1688 :returns: The range.
1689 """
1690 return self._range
1692 def __str__(self) -> str:
1693 """
1694 Formats the ranged case-generate choice.
1696 **Format:** ``0 to 3``
1698 :returns: Formatted ranged case-generate choice.
1699 """
1700 return str(self._range)
1703@export
1704@abstractclass
1705class ConcurrentCase(BaseCase, LabeledEntityMixin, ConcurrentDeclarationRegionMixin, ConcurrentStatementsMixin, AllowBlackboxMixin, ChoicesMixin):
1706 """
1707 Represents the base-class of all alternatives of a case-generate statement.
1709 .. seealso::
1711 * :class:`Generate case <pyVHDLModel.Concurrent.GenerateCase>`
1712 * :class:`Others generate case <pyVHDLModel.Concurrent.OthersGenerateCase>`
1713 """
1714 def __init__(
1715 self,
1716 declaredItems: Nullable[Iterable] = None,
1717 statements: Nullable[Iterable[ConcurrentStatement]] = None,
1718 alternativeLabel: Nullable[str] = None,
1719 choices: Nullable[Iterable[BaseChoice]] = None,
1720 allowBlackbox: Nullable[bool] = None,
1721 parent: Nullable[ModelEntity] = None
1722 ) -> None:
1723 """
1724 Initializes a concurrent case.
1726 :param declaredItems: List of all declared items in this concurrent declaration region.
1727 :param statements: List of all concurrent statements in this construct.
1728 :param alternativeLabel: The alternative's label.
1729 :param choices: List of all choices selecting this alternative.
1730 :param allowBlackbox: Allow blackboxes for components in language entity.
1731 :param parent: The parent model entity of this entity.
1732 """
1733 super().__init__(parent)
1734 LabeledEntityMixin.__init__(self, alternativeLabel)
1736 # TODO: Why not handover self?
1737 # This allows access to Label and NormalizedLabel, also to create a full instance path in case a lookup goes wrong.
1738 ConcurrentDeclarationRegionMixin.__init__(self, self._normalizedLabel, declaredItems)
1739 if parent is not None: 1739 ↛ 1740line 1739 didn't jump to line 1740 because the condition on line 1739 was never true
1740 self._namespace.ParentNamespace = parent._namespace
1742 ConcurrentStatementsMixin.__init__(self, statements)
1743 AllowBlackboxMixin.__init__(self, allowBlackbox)
1744 ChoicesMixin.__init__(self, choices)
1747@export
1748class GenerateCase(ConcurrentCase):
1749 """
1750 Represents one alternative of a case-generate statement, selected by its choices.
1752 .. admonition:: Example
1754 .. code-block:: VHDL
1756 when 8 =>
1757 -- ^ <- Choices
1758 """
1759 def __init__(
1760 self,
1761 choices: Iterable[ConcurrentChoice],
1762 declaredItems: Nullable[Iterable] = None,
1763 statements: Nullable[Iterable[ConcurrentStatement]] = None,
1764 alternativeLabel: Nullable[str] = None,
1765 allowBlackbox: Nullable[bool] = None,
1766 parent: Nullable[ModelEntity] = None
1767 ) -> None:
1768 """
1769 Initializes a generate case.
1771 :param choices: List of all choices selecting this alternative.
1772 :param declaredItems: List of all declared items in this concurrent declaration region.
1773 :param statements: List of all concurrent statements in this construct.
1774 :param alternativeLabel: The alternative's label.
1775 :param allowBlackbox: Allow blackboxes for components in language entity.
1776 :param parent: The parent model entity of this entity.
1777 """
1778 super().__init__(declaredItems, statements, alternativeLabel, choices, allowBlackbox, parent)
1780 def Visit(self, visitor: Visitor) -> None:
1781 """
1782 Walk this case-generate alternative, its choices, its declared items and its statements with a visitor.
1784 :param visitor: The visitor receiving the events.
1785 """
1786 visitor.VisitGenerateCase(self)
1787 for index, choice in enumerate(self._choices):
1788 if index > 0:
1789 visitor.VisitBar(self)
1791 choice.Visit(visitor)
1793 visitor.VisitArrow(self)
1794 self._VisitDeclaredItems(visitor)
1795 visitor.VisitBegin(self)
1796 self._VisitStatements(visitor)
1797 visitor.DepartGenerateCase(self)
1799 def __str__(self) -> str:
1800 """
1801 Formats the case-generate alternative.
1803 **Format:** ``when 0 | 1 =>``
1805 :returns: Formatted case-generate alternative.
1806 """
1807 return "when {choices} =>".format(choices=" | ".join(str(c) for c in self._choices))
1810@export
1811class OthersGenerateCase(ConcurrentCase):
1812 """
1813 Represents the ``others`` alternative of a case-generate statement.
1815 It covers every choice not named explicitly.
1817 .. admonition:: Example
1819 .. code-block:: VHDL
1821 when others =>
1822 -- ^^^^^^ <- the choice
1823 """
1824 def Visit(self, visitor: Visitor) -> None:
1825 """
1826 Walk this ``others`` case-generate alternative, its declared items and its statements with a visitor.
1828 :param visitor: The visitor receiving the events.
1829 """
1830 visitor.VisitOthersGenerateCase(self)
1831 visitor.VisitArrow(self)
1832 self._VisitDeclaredItems(visitor)
1833 visitor.VisitBegin(self)
1834 self._VisitStatements(visitor)
1835 visitor.DepartOthersGenerateCase(self)
1837 def __str__(self) -> str:
1838 """
1839 Formats the ``others`` case-generate alternative.
1841 **Format:** ``when others =>``
1843 :returns: Formatted ``others`` case-generate alternative.
1844 """
1845 return "when others =>"
1848@export
1849class CaseGenerateStatement(GenerateStatement):
1850 """
1851 Represents a case-generate statement.
1853 The expression being tested is available as :data:`SelectExpression`, the alternatives as
1854 :data:`Cases`. The label is mandatory and the selector must be a static expression.
1856 .. admonition:: Example
1858 .. code-block:: VHDL
1860 gen : case MODE generate
1861 --^^^ <- Label
1862 -- ^^^^ <- SelectExpression
1863 when 0 => q <= '0';
1864 -- ^^^^^^^^^^^^^^^^^^^ <- Cases[0]
1865 when others => q <= '1';
1866 -- ^^^^^^^^^^^^^^^^^^^^^^^^ <- Cases[1]
1867 end generate;
1869 .. seealso::
1871 * :class:`If-generate statement <pyVHDLModel.Concurrent.IfGenerateStatement>`
1872 * :class:`For-generate statement <pyVHDLModel.Concurrent.ForGenerateStatement>`
1873 """
1875 _expression: ExpressionUnion #: The expression being tested; it must be static.
1876 _cases: list[GenerateCase] #: List of all alternatives, in the order they were written.
1878 def __init__(
1879 self,
1880 label: str,
1881 expression: ExpressionUnion,
1882 cases: Iterable[ConcurrentCase],
1883 allowBlackbox: Nullable[bool] = None,
1884 parent: Nullable[ModelEntity] = None
1885 ) -> None:
1886 """
1887 Initializes a case-generate statement.
1889 :param label: The label of a model entity.
1890 :param expression: The expression being tested; it must be static.
1891 :param cases: List of all alternatives, in the order they were written.
1892 :param allowBlackbox: Allow blackboxes for components in language entity.
1893 :param parent: The parent model entity of this entity.
1894 """
1895 super().__init__(label, allowBlackbox, parent)
1897 self._expression = expression
1898 expression.Parent = self
1900 # TODO: create a mixin for things with cases
1901 self._cases = caseList = []
1902 if cases is not None: 1902 ↛ exitline 1902 didn't return from function '__init__' because the condition on line 1902 was always true
1903 for case in cases:
1904 caseList.append(case)
1905 case.Parent = self
1907 def Visit(self, visitor: Visitor) -> None:
1908 """
1909 Walk this case-generate statement, its selector and its alternatives with a visitor.
1911 :param visitor: The visitor receiving the events.
1912 """
1913 visitor.VisitCaseGenerateStatement(self)
1914 self._expression.Visit(visitor)
1915 visitor.VisitGenerate(self)
1916 for case in self._cases:
1917 case.Visit(visitor)
1919 visitor.DepartCaseGenerateStatement(self)
1921 @GenerateStatement.Parent.setter
1922 def Parent(self, parent: ModelEntity) -> None:
1923 GenerateStatement.Parent.fset(self, parent)
1925 # Connect namespaces
1926 for case in self._cases:
1927 case._namespace.ParentNamespace = parent._namespace
1929 @readonly
1930 def SelectExpression(self) -> ExpressionUnion:
1931 """
1932 Read-only property to access the select expression (:attr:`_expression`).
1934 :returns: The select expression.
1935 """
1936 return self._expression
1938 @readonly
1939 def Cases(self) -> list[GenerateCase]:
1940 """
1941 Read-only property to access the cases (:attr:`_cases`).
1943 :returns: List of cases.
1944 """
1945 return self._cases
1947 def IterateInstantiations(self) -> Generator[Instantiation, None, None]:
1948 for case in self._cases:
1949 yield from case.IterateInstantiations()
1951 def IndexStatement(self) -> None:
1952 for case in self._cases:
1953 case.IndexStatements()
1956@export
1957class ForGenerateStatement(GenerateStatement, ConcurrentDeclarationRegionMixin, ConcurrentStatementsMixin):
1958 """
1959 Represents a for-generate statement.
1961 The loop index is available as :data:`LoopIndex`, the iteration range as :data:`Range` and the
1962 generated statements as :data:`Statements`. The label is mandatory.
1964 .. admonition:: Example
1966 .. code-block:: VHDL
1968 gen : for i in 0 to 3 generate
1969 --^^^ <- Label
1970 -- ^ <- LoopIndex
1971 -- ^^^^^^ <- Range
1972 q(i) <= '0';
1973 -- ^^^^^^^^^^^^ <- Statements
1974 end generate;
1976 .. seealso::
1978 * :class:`If-generate statement <pyVHDLModel.Concurrent.IfGenerateStatement>`
1979 * :class:`Case-generate statement <pyVHDLModel.Concurrent.CaseGenerateStatement>`
1980 """
1982 _loopIndex: str #: The name of the generate loop's index.
1983 _range: Range #: The range the generate loop iterates over.
1985 def __init__(
1986 self,
1987 label: str,
1988 loopIndex: str,
1989 rng: Range,
1990 declaredItems: Nullable[Iterable] = None,
1991 statements: Nullable[Iterable[ConcurrentStatement]] = None,
1992 allowBlackbox: Nullable[bool] = None,
1993 parent: Nullable[ModelEntity] = None
1994 ) -> None:
1995 """
1996 Initializes a for-generate statement.
1998 :param label: The label of a model entity.
1999 :param loopIndex: The name of the generate loop's index.
2000 :param rng: The range the generate loop iterates over.
2001 :param declaredItems: List of all declared items in this concurrent declaration region.
2002 :param statements: List of all concurrent statements in this construct.
2003 :param allowBlackbox: Allow blackboxes for components in language entity.
2004 :param parent: The parent model entity of this entity.
2005 """
2006 super().__init__(label, allowBlackbox, parent)
2008 ConcurrentDeclarationRegionMixin.__init__(self, self._normalizedLabel, declaredItems)
2009 if parent is not None: 2009 ↛ 2010line 2009 didn't jump to line 2010 because the condition on line 2009 was never true
2010 self._namespace.ParentNamespace = parent._namespace
2012 ConcurrentStatementsMixin.__init__(self, statements)
2014 self._loopIndex = loopIndex
2016 self._range = rng
2017 rng.Parent = self
2019 def Visit(self, visitor: Visitor) -> None:
2020 """
2021 Walk this for-generate statement, its range, its declared items and its statements with a visitor.
2023 :param visitor: The visitor receiving the events.
2024 """
2025 visitor.VisitForGenerateStatement(self)
2026 self._range.Visit(visitor)
2027 visitor.VisitGenerate(self)
2028 self._VisitDeclaredItems(visitor)
2029 visitor.VisitBegin(self)
2030 self._VisitStatements(visitor)
2031 visitor.DepartForGenerateStatement(self)
2033 @GenerateStatement.Parent.setter
2034 def Parent(self, parent: ModelEntity) -> None:
2035 GenerateStatement.Parent.fset(self, parent)
2037 self._namespace.ParentNamespace = parent._namespace
2039 @readonly
2040 def LoopIndex(self) -> str:
2041 """
2042 Read-only property to access the loop index (:attr:`_loopIndex`).
2044 :returns: The loop index.
2045 """
2046 return self._loopIndex
2048 @readonly
2049 def Range(self) -> Range:
2050 """
2051 Read-only property to access the range (:attr:`_range`).
2053 :returns: The range.
2054 """
2055 return self._range
2057 # IndexDeclaredItems = ConcurrentStatements.IndexDeclaredItems
2059 def IndexStatement(self) -> None:
2060 self.IndexStatements()
2062 def IndexStatements(self) -> None:
2063 super().IndexStatements()
2065 def IterateInstantiations(self) -> Generator[Instantiation, None, None]:
2066 return ConcurrentStatementsMixin.IterateInstantiations(self)
2069@export
2070@abstractclass
2071class ConcurrentSignalAssignment(ConcurrentStatement, SignalAssignmentMixin):
2072 """
2073 Represents the base-class of all concurrent signal assignments.
2075 .. seealso::
2077 * :class:`Concurrent simple signal assignment <pyVHDLModel.Concurrent.ConcurrentSimpleSignalAssignment>`
2078 * :class:`Concurrent selected signal assignment <pyVHDLModel.Concurrent.ConcurrentSelectedSignalAssignment>`
2079 * :class:`Conditional signal assignment <pyVHDLModel.Concurrent.ConcurrentConditionalSignalAssignment>` """
2080 def __init__(self, label: Nullable[str], target: SignalSymbol, parent: Nullable[ModelEntity] = None) -> None:
2081 """
2082 Initializes a concurrent signal assignment.
2084 :param label: The label of a model entity.
2085 :param target: Reference to the assignment's destination.
2086 :param parent: The parent model entity of this entity.
2087 """
2088 super().__init__(label, parent)
2089 SignalAssignmentMixin.__init__(self, target)
2092@export
2093class ConcurrentSimpleSignalAssignment(ConcurrentSignalAssignment, WaveformMixin):
2094 """
2095 Represents a simple concurrent signal assignment.
2097 The assignment's destination is available as :data:`Target`, its value as :data:`Waveform`.
2099 .. admonition:: Example
2101 .. code-block:: VHDL
2103 lbl : q <= '1';
2104 --^^^ <- optional Label
2105 -- ^ <- Target
2106 -- ^^^ <- Waveform
2108 .. seealso::
2110 * :class:`Sequential counterpart <pyVHDLModel.Sequential.SequentialSimpleSignalAssignment>`
2111 """
2112 def __init__(
2113 self,
2114 label: Nullable[str],
2115 target: SignalSymbol,
2116 waveform: Iterable[WaveformElement],
2117 parent: Nullable[ModelEntity] = None
2118 ) -> None:
2119 """
2120 Initializes a simple concurrent signal assignment.
2122 :param label: The label of a model entity.
2123 :param target: Reference to the assignment's destination.
2124 :param waveform: List of all waveform elements, in the order they were written.
2125 :param parent: The parent model entity of this entity.
2126 """
2127 super().__init__(label, target, parent)
2128 WaveformMixin.__init__(self, waveform)
2130 def Visit(self, visitor: Visitor) -> None:
2131 """
2132 Walk this concurrent signal assignment, its target and its waveform with a visitor.
2134 :param visitor: The visitor receiving the events.
2135 """
2136 visitor.VisitConcurrentSimpleSignalAssignment(self)
2137 self._target.Visit(visitor)
2138 visitor.VisitSignalAssignment(self)
2139 self._VisitWaveform(visitor)
2140 visitor.DepartConcurrentSimpleSignalAssignment(self)
2143@export
2144class ConcurrentSelectedSignalAssignment(ConcurrentSignalAssignment, ExpressionMixin, SelectedWaveformsMixin):
2145 """
2146 Represents a selected concurrent signal assignment.
2148 The selector is available as :data:`Expression`, the alternatives as :data:`SelectedWaveforms`,
2149 a list of :class:`~pyVHDLModel.Common.SelectedWaveform`. The model holds them in a list and has
2150 no distinct field per alternative, so the markers below name list elements.
2152 .. admonition:: Example
2154 .. code-block:: VHDL
2156 lbl : with sel select q <= '1' when '0', '0' when others;
2157 --^^^ <- optional Label
2158 -- ^^^ <- Expression
2159 -- ^ <- Target
2160 -- ^^^^^^^^^^^^ <- SelectedWaveforms[0]
2161 -- ^^^^^^^^^^^^^^^ <- SelectedWaveforms[1]
2163 .. seealso::
2165 * :class:`Sequential counterpart <pyVHDLModel.Sequential.SequentialSelectedSignalAssignment>`
2166 * :class:`Selected waveform <pyVHDLModel.Common.SelectedWaveform>`
2167 """
2169 def __init__(
2170 self,
2171 label: Nullable[str],
2172 target: SignalSymbol,
2173 expression: ExpressionUnion,
2174 selectedWaveforms: Iterable[SelectedWaveform],
2175 parent: Nullable[ModelEntity] = None
2176 ) -> None:
2177 """
2178 Initializes a selected concurrent signal assignment.
2180 :param label: The label of a model entity.
2181 :param target: Reference to the assignment's destination.
2182 :param expression: The selector expression.
2183 :param selectedWaveforms: All alternatives, in order.
2184 :param parent: The parent model entity of this entity.
2185 """
2186 super().__init__(label, target, parent)
2187 ExpressionMixin.__init__(self, expression)
2188 SelectedWaveformsMixin.__init__(self, selectedWaveforms)
2190 def Visit(self, visitor: Visitor) -> None:
2191 """
2192 Walk this selected signal assignment, its selector, its target and its alternatives with a visitor.
2194 :param visitor: The visitor receiving the events.
2195 """
2196 visitor.VisitConcurrentSelectedSignalAssignment(self)
2197 self._expression.Visit(visitor)
2198 visitor.VisitSelect(self)
2199 self._target.Visit(visitor)
2200 visitor.VisitSignalAssignment(self)
2201 self._VisitSelectedWaveforms(visitor)
2202 visitor.DepartConcurrentSelectedSignalAssignment(self)
2205@export
2206class ConcurrentConditionalSignalAssignment(ConcurrentSignalAssignment, ConditionalWaveformsMixin):
2207 """
2208 Represents a conditional concurrent signal assignment.
2210 The alternatives are available as :data:`ConditionalWaveforms`, a list of
2211 :class:`~pyVHDLModel.Common.ConditionalWaveform`. The model holds them in a list and has no
2212 distinct field per alternative, so the markers below name list elements.
2214 .. admonition:: Example
2216 .. code-block:: VHDL
2218 lbl : q <= '1' when cond else '0';
2219 --^^^ <- optional Label
2220 -- ^ <- Target
2221 -- ^^^^^^^^^^^^^ <- ConditionalWaveforms[0]
2222 -- ^^^ <- ConditionalWaveforms[1]
2224 .. seealso::
2226 * :class:`Sequential counterpart <pyVHDLModel.Sequential.SequentialConditionalSignalAssignment>`
2227 * :class:`Conditional waveform <pyVHDLModel.Common.ConditionalWaveform>`
2228 """
2230 def __init__(
2231 self,
2232 label: Nullable[str],
2233 target: SignalSymbol,
2234 conditionalWaveforms: Iterable[ConditionalWaveform],
2235 parent: Nullable[ModelEntity] = None
2236 ) -> None:
2237 """
2238 Initializes a conditional concurrent signal assignment.
2240 :param label: The label of a model entity.
2241 :param target: Reference to the assignment's destination.
2242 :param conditionalWaveforms: All alternatives, in order.
2243 :param parent: The parent model entity of this entity.
2244 """
2245 super().__init__(label, target, parent)
2246 ConditionalWaveformsMixin.__init__(self, conditionalWaveforms)
2248 def Visit(self, visitor: Visitor) -> None:
2249 """
2250 Walk this conditional signal assignment, its target and its alternatives with a visitor.
2252 :param visitor: The visitor receiving the events.
2253 """
2254 visitor.VisitConcurrentConditionalSignalAssignment(self)
2255 self._target.Visit(visitor)
2256 visitor.VisitSignalAssignment(self)
2257 self._VisitConditionalWaveforms(visitor)
2258 visitor.DepartConcurrentConditionalSignalAssignment(self)
2261@export
2262class ConcurrentAssertStatement(ConcurrentStatement, AssertStatementMixin):
2263 """
2264 Represents a concurrent assertion statement.
2266 The checked condition is available as :data:`Condition`, the optional report string as
2267 :data:`Message` and the optional severity as :data:`Severity`.
2269 .. admonition:: Example
2271 .. code-block:: VHDL
2273 lbl : assert cond report "bad" severity note;
2274 --^^^ <- optional Label
2275 -- ^^^^ <- Condition
2276 -- ^^^^^ <- optional Message
2277 -- ^^^^ <- optional Severity
2279 .. seealso::
2281 * :class:`Sequential counterpart <pyVHDLModel.Sequential.SequentialAssertStatement>`
2282 """
2283 def __init__(
2284 self,
2285 condition: ExpressionUnion,
2286 message: Nullable[ExpressionUnion] = None,
2287 severity: Nullable[ExpressionUnion] = None,
2288 label: Nullable[str] = None,
2289 parent: Nullable[ModelEntity] = None
2290 ) -> None:
2291 """
2292 Initializes a concurrent assertion statement.
2294 :param condition: The condition guarding this statement.
2295 :param message: The reported message, or ``None`` if none was given.
2296 :param severity: The reported severity level, or ``None`` if none was given.
2297 :param label: The label of a model entity.
2298 :param parent: The parent model entity of this entity.
2299 """
2300 super().__init__(label, parent)
2301 AssertStatementMixin.__init__(self, condition, message, severity)
2303 def Visit(self, visitor: Visitor) -> None:
2304 """
2305 Walk this concurrent assertion, its condition, its message and its severity with a visitor.
2307 :param visitor: The visitor receiving the events.
2308 """
2309 visitor.VisitConcurrentAssertStatement(self)
2310 self._VisitAssertion(visitor)
2311 visitor.DepartConcurrentAssertStatement(self)