Coverage for pyVHDLModel/Sequential.py: 52%
270 statements
« prev ^ index » next coverage.py v7.6.9, created at 2024-12-20 22:13 +0000
« prev ^ index » next coverage.py v7.6.9, created at 2024-12-20 22:13 +0000
1# ==================================================================================================================== #
2# __ ___ _ ____ _ __ __ _ _ #
3# _ __ _ \ \ / / | | | _ \| | | \/ | ___ __| | ___| | #
4# | '_ \| | | \ \ / /| |_| | | | | | | |\/| |/ _ \ / _` |/ _ \ | #
5# | |_) | |_| |\ V / | _ | |_| | |___| | | | (_) | (_| | __/ | #
6# | .__/ \__, | \_/ |_| |_|____/|_____|_| |_|\___/ \__,_|\___|_| #
7# |_| |___/ #
8# ==================================================================================================================== #
9# Authors: #
10# Patrick Lehmann #
11# #
12# License: #
13# ==================================================================================================================== #
14# Copyright 2017-2024 Patrick Lehmann - Boetzingen, Germany #
15# Copyright 2016-2017 Patrick Lehmann - Dresden, Germany #
16# #
17# Licensed under the Apache License, Version 2.0 (the "License"); #
18# you may not use this file except in compliance with the License. #
19# You may obtain a copy of the License at #
20# #
21# http://www.apache.org/licenses/LICENSE-2.0 #
22# #
23# Unless required by applicable law or agreed to in writing, software #
24# distributed under the License is distributed on an "AS IS" BASIS, #
25# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
26# See the License for the specific language governing permissions and #
27# limitations under the License. #
28# #
29# SPDX-License-Identifier: Apache-2.0 #
30# ==================================================================================================================== #
31#
32"""
33This module contains parts of an abstract document language model for VHDL.
35Declarations for sequential statements.
36"""
37from typing import List, Iterable, Optional as Nullable
39from pyTooling.Decorators import export, readonly
40from pyTooling.MetaClasses import ExtendedType
42from pyVHDLModel.Base import ModelEntity, ExpressionUnion, Range, BaseChoice, BaseCase, ConditionalMixin, IfBranchMixin, ElsifBranchMixin
43from pyVHDLModel.Base import ElseBranchMixin, ReportStatementMixin, AssertStatementMixin, WaveformElement
44from pyVHDLModel.Symbol import Symbol
45from pyVHDLModel.Common import Statement, ProcedureCallMixin
46from pyVHDLModel.Common import SignalAssignmentMixin, VariableAssignmentMixin
47from pyVHDLModel.Association import ParameterAssociationItem
50@export
51class SequentialStatement(Statement):
52 """A ``SequentialStatement`` is a base-class for all sequential statements."""
55@export
56class SequentialStatementsMixin(metaclass=ExtendedType, mixin=True):
57 _statements: List[SequentialStatement]
59 def __init__(self, statements: Nullable[Iterable[SequentialStatement]] = None) -> None:
60 # TODO: extract to mixin
61 self._statements = []
62 if statements is not None:
63 for item in statements:
64 self._statements.append(item)
65 item._parent = self
67 @readonly
68 def Statements(self) -> List[SequentialStatement]:
69 """
70 Read-only property to access the list of sequential statements (:attr:`_statements`).
72 :returns: A list of sequential statements.
73 """
74 return self._statements
77@export
78class SequentialProcedureCall(SequentialStatement, ProcedureCallMixin):
79 def __init__(
80 self,
81 procedureName: Symbol,
82 parameterMappings: Nullable[Iterable[ParameterAssociationItem]] = None,
83 label: Nullable[str] = None,
84 parent: ModelEntity = None
85 ) -> None:
86 super().__init__(label, parent)
87 ProcedureCallMixin.__init__(self, procedureName, parameterMappings)
90@export
91class SequentialSignalAssignment(SequentialStatement, SignalAssignmentMixin):
92 def __init__(self, target: Symbol, label: Nullable[str] = None, parent: ModelEntity = None) -> None:
93 super().__init__(label, parent)
94 SignalAssignmentMixin.__init__(self, target)
97@export
98class SequentialSimpleSignalAssignment(SequentialSignalAssignment):
99 _waveform: List[WaveformElement]
101 def __init__(self, target: Symbol, waveform: Iterable[WaveformElement], label: Nullable[str] = None, parent: ModelEntity = None) -> None:
102 super().__init__(target, label, parent)
104 # TODO: extract to mixin
105 self._waveform = []
106 if waveform is not None:
107 for waveformElement in waveform:
108 self._waveform.append(waveformElement)
109 waveformElement._parent = self
111 @readonly
112 def Waveform(self) -> List[WaveformElement]:
113 """
114 Read-only property to access the list waveform elements (:attr:`_waveform`).
116 :returns: A list of waveform elements.
117 """
118 return self._waveform
121@export
122class SequentialVariableAssignment(SequentialStatement, VariableAssignmentMixin):
123 def __init__(self, target: Symbol, expression: ExpressionUnion, label: Nullable[str] = None, parent: ModelEntity = None) -> None:
124 super().__init__(label, parent)
125 VariableAssignmentMixin.__init__(self, target, expression)
128@export
129class SequentialReportStatement(SequentialStatement, ReportStatementMixin):
130 def __init__(self, message: ExpressionUnion, severity: Nullable[ExpressionUnion] = None, label: Nullable[str] = None, parent: ModelEntity = None) -> None:
131 super().__init__(label, parent)
132 ReportStatementMixin.__init__(self, message, severity)
135@export
136class SequentialAssertStatement(SequentialStatement, AssertStatementMixin):
137 def __init__(
138 self,
139 condition: ExpressionUnion,
140 message: Nullable[ExpressionUnion] = None,
141 severity: Nullable[ExpressionUnion] = None,
142 label: Nullable[str] = None,
143 parent: ModelEntity = None
144 ) -> None:
145 super().__init__(label, parent)
146 AssertStatementMixin.__init__(self, condition, message, severity)
149@export
150class CompoundStatement(SequentialStatement):
151 """A ``CompoundStatement`` is a base-class for all compound statements."""
154@export
155class Branch(ModelEntity, SequentialStatementsMixin):
156 """A ``Branch`` is a base-class for all branches in a if statement."""
158 def __init__(self, statements: Nullable[Iterable[SequentialStatement]] = None, parent: ModelEntity = None) -> None:
159 super().__init__(parent)
160 SequentialStatementsMixin.__init__(self, statements)
163@export
164class IfBranch(Branch, IfBranchMixin):
165 def __init__(self, condition: ExpressionUnion, statements: Nullable[Iterable[SequentialStatement]] = None, parent: ModelEntity = None) -> None:
166 super().__init__(statements, parent)
167 IfBranchMixin.__init__(self, condition)
170@export
171class ElsifBranch(Branch, ElsifBranchMixin):
172 def __init__(self, condition: ExpressionUnion, statements: Nullable[Iterable[SequentialStatement]] = None, parent: ModelEntity = None) -> None:
173 super().__init__(statements, parent)
174 ElsifBranchMixin.__init__(self, condition)
177@export
178class ElseBranch(Branch, ElseBranchMixin):
179 def __init__(self, statements: Nullable[Iterable[SequentialStatement]] = None, parent: ModelEntity = None) -> None:
180 super().__init__(statements, parent)
181 ElseBranchMixin.__init__(self)
184@export
185class IfStatement(CompoundStatement):
186 _ifBranch: IfBranch
187 _elsifBranches: List['ElsifBranch']
188 _elseBranch: Nullable[ElseBranch]
190 def __init__(
191 self,
192 ifBranch: IfBranch,
193 elsifBranches: Nullable[Iterable[ElsifBranch]] = None,
194 elseBranch: Nullable[ElseBranch] = None,
195 label: Nullable[str] = None,
196 parent: ModelEntity = None
197 ) -> None:
198 super().__init__(label, parent)
200 self._ifBranch = ifBranch
201 ifBranch._parent = self
203 self._elsifBranches = []
204 if elsifBranches is not None:
205 for branch in elsifBranches:
206 self._elsifBranches.append(branch)
207 branch._parent = self
209 if elseBranch is not None:
210 self._elseBranch = elseBranch
211 elseBranch._parent = self
212 else:
213 self._elseBranch = None
215 @readonly
216 def IfBranch(self) -> IfBranch:
217 """
218 Read-only property to access the if-branch of the if-statement (:attr:`_ifBranch`).
220 :returns: The if-branch.
221 """
222 return self._ifBranch
224 @property
225 def ElsIfBranches(self) -> List['ElsifBranch']:
226 """
227 Read-only property to access the elsif-branch of the if-statement (:attr:`_elsifBranch`).
229 :returns: The elsif-branch.
230 """
231 return self._elsifBranches
233 @property
234 def ElseBranch(self) -> Nullable[ElseBranch]:
235 """
236 Read-only property to access the else-branch of the if-statement (:attr:`_elseBranch`).
238 :returns: The else-branch.
239 """
240 return self._elseBranch
243@export
244class SequentialChoice(BaseChoice):
245 """A ``SequentialChoice`` is a base-class for all sequential choices (in case statements)."""
248@export
249class IndexedChoice(SequentialChoice):
250 _expression: ExpressionUnion
252 def __init__(self, expression: ExpressionUnion, parent: ModelEntity = None) -> None:
253 super().__init__(parent)
255 self._expression = expression
256 # expression._parent = self # FIXME: received None
258 @property
259 def Expression(self) -> ExpressionUnion:
260 return self._expression
262 def __str__(self) -> str:
263 return str(self._expression)
266@export
267class RangedChoice(SequentialChoice):
268 _range: 'Range'
270 def __init__(self, rng: 'Range', parent: ModelEntity = None) -> None:
271 super().__init__(parent)
273 self._range = rng
274 rng._parent = self
276 @property
277 def Range(self) -> 'Range':
278 return self._range
280 def __str__(self) -> str:
281 return str(self._range)
284@export
285class SequentialCase(BaseCase, SequentialStatementsMixin):
286 _choices: List
288 def __init__(self, statements: Nullable[Iterable[SequentialStatement]] = None, parent: ModelEntity = None) -> None:
289 super().__init__(parent)
290 SequentialStatementsMixin.__init__(self, statements)
292 # TODO: what about choices?
294 @property
295 def Choices(self) -> List[BaseChoice]:
296 return self._choices
299@export
300class Case(SequentialCase):
301 def __init__(self, choices: Iterable[SequentialChoice], statements: Nullable[Iterable[SequentialStatement]] = None, parent: ModelEntity = None) -> None:
302 super().__init__(statements, parent)
304 self._choices = []
305 if choices is not None:
306 for choice in choices:
307 self._choices.append(choice)
308 choice._parent = self
310 @property
311 def Choices(self) -> List[SequentialChoice]:
312 return self._choices
314 def __str__(self) -> str:
315 return "when {choices} =>".format(choices=" | ".join(str(c) for c in self._choices))
318@export
319class OthersCase(SequentialCase):
320 def __str__(self) -> str:
321 return "when others =>"
324@export
325class CaseStatement(CompoundStatement):
326 _expression: ExpressionUnion
327 _cases: List[SequentialCase]
329 def __init__(self, expression: ExpressionUnion, cases: Iterable[SequentialCase], label: Nullable[str] = None, parent: ModelEntity = None) -> None:
330 super().__init__(label, parent)
332 self._expression = expression
333 expression._parent = self
335 self._cases = []
336 if cases is not None:
337 for case in cases:
338 self._cases.append(case)
339 case._parent = self
341 @property
342 def SelectExpression(self) -> ExpressionUnion:
343 return self._expression
345 @property
346 def Cases(self) -> List[SequentialCase]:
347 return self._cases
350@export
351class LoopStatement(CompoundStatement, SequentialStatementsMixin):
352 """A ``LoopStatement`` is a base-class for all loop statements."""
354 def __init__(self, statements: Nullable[Iterable[SequentialStatement]] = None, label: Nullable[str] = None, parent: ModelEntity = None) -> None:
355 super().__init__(label, parent)
356 SequentialStatementsMixin.__init__(self, statements)
359@export
360class EndlessLoopStatement(LoopStatement):
361 pass
364@export
365class ForLoopStatement(LoopStatement):
366 _loopIndex: str
367 _range: Range
369 def __init__(self, loopIndex: str, rng: Range, statements: Nullable[Iterable[SequentialStatement]] = None, label: Nullable[str] = None, parent: ModelEntity = None) -> None:
370 super().__init__(statements, label, parent)
372 self._loopIndex = loopIndex
374 self._range = rng
375 rng._parent = self
377 @property
378 def LoopIndex(self) -> str:
379 return self._loopIndex
381 @property
382 def Range(self) -> Range:
383 return self._range
386@export
387class WhileLoopStatement(LoopStatement, ConditionalMixin):
388 def __init__(
389 self,
390 condition: ExpressionUnion,
391 statements: Nullable[Iterable[SequentialStatement]] = None,
392 label: Nullable[str] = None,
393 parent: ModelEntity = None
394 ) -> None:
395 super().__init__(statements, label, parent)
396 ConditionalMixin.__init__(self, condition)
399@export
400class LoopControlStatement(SequentialStatement, ConditionalMixin):
401 """A ``LoopControlStatement`` is a base-class for all loop controlling statements."""
403 _loopReference: LoopStatement
405 def __init__(self, condition: Nullable[ExpressionUnion] = None, loopLabel: Nullable[str] = None, parent: ModelEntity = None) -> None: # TODO: is this label (currently str) a Name or a Label class?
406 super().__init__(parent)
407 ConditionalMixin.__init__(self, condition)
409 # TODO: loopLabel
410 # TODO: loop reference -> is it a symbol?
412 @property
413 def LoopReference(self) -> LoopStatement:
414 return self._loopReference
417@export
418class NextStatement(LoopControlStatement):
419 pass
422@export
423class ExitStatement(LoopControlStatement):
424 pass
427@export
428class NullStatement(SequentialStatement):
429 pass
432@export
433class ReturnStatement(SequentialStatement, ConditionalMixin):
434 _returnValue: ExpressionUnion
436 def __init__(self, returnValue: Nullable[ExpressionUnion] = None, parent: ModelEntity = None) -> None:
437 super().__init__(parent)
438 ConditionalMixin.__init__(self, returnValue)
440 # TODO: return value?
442 @property
443 def ReturnValue(self) -> ExpressionUnion:
444 return self._returnValue
447@export
448class WaitStatement(SequentialStatement, ConditionalMixin):
449 _sensitivityList: Nullable[List[Symbol]]
450 _timeout: ExpressionUnion
452 def __init__(
453 self,
454 sensitivityList: Nullable[Iterable[Symbol]] = None,
455 condition: Nullable[ExpressionUnion] = None,
456 timeout: Nullable[ExpressionUnion] = None,
457 label: Nullable[str] = None,
458 parent: ModelEntity = None
459 ) -> None:
460 super().__init__(label, parent)
461 ConditionalMixin.__init__(self, condition)
463 if sensitivityList is None:
464 self._sensitivityList = None
465 else:
466 self._sensitivityList = [] # TODO: convert to dict
467 for signalSymbol in sensitivityList:
468 self._sensitivityList.append(signalSymbol)
469 signalSymbol._parent = self
471 self._timeout = timeout
472 if timeout is not None:
473 timeout._parent = self
475 @property
476 def SensitivityList(self) -> List[Symbol]:
477 return self._sensitivityList
479 @property
480 def Timeout(self) -> ExpressionUnion:
481 return self._timeout
484@export
485class SequentialDeclarationsMixin(metaclass=ExtendedType, mixin=True):
486 _declaredItems: List
488 def __init__(self, declaredItems: Iterable) -> None:
489 # TODO: extract to mixin
490 self._declaredItems = [] # TODO: convert to dict
491 if declaredItems is not None:
492 for item in declaredItems:
493 self._declaredItems.append(item)
494 item._parent = self
496 @property
497 def DeclaredItems(self) -> List:
498 return self._declaredItems