Source code for pyVHDLModel.Sequential

# ==================================================================================================================== #
#             __     ___   _ ____  _     __  __           _      _                                                     #
#   _ __  _   \ \   / / | | |  _ \| |   |  \/  | ___   __| | ___| |                                                    #
#  | '_ \| | | \ \ / /| |_| | | | | |   | |\/| |/ _ \ / _` |/ _ \ |                                                    #
#  | |_) | |_| |\ V / |  _  | |_| | |___| |  | | (_) | (_| |  __/ |                                                    #
#  | .__/ \__, | \_/  |_| |_|____/|_____|_|  |_|\___/ \__,_|\___|_|                                                    #
#  |_|    |___/                                                                                                        #
# ==================================================================================================================== #
# Authors:                                                                                                             #
#   Patrick Lehmann                                                                                                    #
#                                                                                                                      #
# License:                                                                                                             #
# ==================================================================================================================== #
# Copyright 2017-2023 Patrick Lehmann - Boetzingen, Germany                                                            #
# Copyright 2016-2017 Patrick Lehmann - Dresden, Germany                                                               #
#                                                                                                                      #
# Licensed under the Apache License, Version 2.0 (the "License");                                                      #
# you may not use this file except in compliance with the License.                                                     #
# You may obtain a copy of the License at                                                                              #
#                                                                                                                      #
#   http://www.apache.org/licenses/LICENSE-2.0                                                                         #
#                                                                                                                      #
# Unless required by applicable law or agreed to in writing, software                                                  #
# distributed under the License is distributed on an "AS IS" BASIS,                                                    #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.                                             #
# See the License for the specific language governing permissions and                                                  #
# limitations under the License.                                                                                       #
#                                                                                                                      #
# SPDX-License-Identifier: Apache-2.0                                                                                  #
# ==================================================================================================================== #
#
"""
This module contains parts of an abstract document language model for VHDL.

Declarations for sequential statements.
"""
from typing                  import List, Iterable, Optional as Nullable

from pyTooling.Decorators    import export

from pyVHDLModel.Base import ModelEntity, ExpressionUnion, Range, BaseChoice, BaseCase, ConditionalMixin, IfBranchMixin, ElsifBranchMixin, ElseBranchMixin, \
	ReportStatementMixin, AssertStatementMixin, WaveformElement
from pyVHDLModel.Symbol      import Symbol
from pyVHDLModel.Common      import Statement, ProcedureCall
from pyVHDLModel.Common      import SignalAssignment, VariableAssignment
from pyVHDLModel.Association import ParameterAssociationItem


@export
class SequentialStatement(Statement):
	"""A ``SequentialStatement`` is a base-class for all sequential statements."""


@export
class SequentialStatements:
	_statements: List[SequentialStatement]

	def __init__(self, statements: Iterable[SequentialStatement] = None):
		# TODO: extract to mixin
		self._statements = []
		if statements is not None:
			for item in statements:
				self._statements.append(item)
				item._parent = self

	@property
	def Statements(self) -> List[SequentialStatement]:
		return self._statements


@export
class SequentialProcedureCall(SequentialStatement, ProcedureCall):
	def __init__(self, procedureName: Symbol, parameterMappings: Iterable[ParameterAssociationItem] = None, label: str = None):
		super().__init__(label)
		ProcedureCall.__init__(self, procedureName, parameterMappings)


@export
class SequentialSignalAssignment(SequentialStatement, SignalAssignment):
	def __init__(self, target: Symbol, label: str = None):
		super().__init__(label)
		SignalAssignment.__init__(self, target)


@export
class SequentialSimpleSignalAssignment(SequentialSignalAssignment):
	_waveform: List[WaveformElement]

	def __init__(self, target: Symbol, waveform: Iterable[WaveformElement], label: str = None):
		super().__init__(target, label)

		# TODO: extract to mixin
		self._waveform = []
		if waveform is not None:
			for waveformElement in waveform:
				self._waveform.append(waveformElement)
				waveformElement._parent = self

	@property
	def Waveform(self) -> List[WaveformElement]:
		return self._waveform


@export
class SequentialVariableAssignment(SequentialStatement, VariableAssignment):
	def __init__(self, target: Symbol, expression: ExpressionUnion, label: str = None):
		super().__init__(label)
		VariableAssignment.__init__(self, target, expression)


@export
class SequentialReportStatement(SequentialStatement, ReportStatementMixin):
	def __init__(self, message: ExpressionUnion, severity: ExpressionUnion = None, label: str = None):
		super().__init__(label)
		ReportStatementMixin.__init__(self, message, severity)


@export
class SequentialAssertStatement(SequentialStatement, AssertStatementMixin):
	def __init__(self, condition: ExpressionUnion, message: ExpressionUnion = None, severity: ExpressionUnion = None, label: str = None):
		super().__init__(label)
		AssertStatementMixin.__init__(self, condition, message, severity)


@export
class CompoundStatement(SequentialStatement):
	"""A ``CompoundStatement`` is a base-class for all compound statements."""


@export
class Branch(ModelEntity, SequentialStatements):
	"""A ``Branch`` is a base-class for all branches in a if statement."""

	def __init__(self, statements: Iterable[SequentialStatement] = None):
		super().__init__()
		SequentialStatements.__init__(self, statements)


@export
class IfBranch(Branch, IfBranchMixin):
	def __init__(self, condition: ExpressionUnion, statements: Iterable[SequentialStatement] = None):
		super().__init__(statements)
		IfBranchMixin.__init__(self, condition)


@export
class ElsifBranch(Branch, ElsifBranchMixin):
	def __init__(self, condition: ExpressionUnion, statements: Iterable[SequentialStatement] = None):
		super().__init__(statements)
		ElsifBranchMixin.__init__(self, condition)


@export
class ElseBranch(Branch, ElseBranchMixin):
	def __init__(self, statements: Iterable[SequentialStatement] = None):
		super().__init__(statements)
		ElseBranchMixin.__init__(self)


@export
class IfStatement(CompoundStatement):
	_ifBranch: IfBranch
	_elsifBranches: List['ElsifBranch']
	_elseBranch: Nullable[ElseBranch]

	def __init__(self, ifBranch: IfBranch, elsifBranches: Iterable[ElsifBranch] = None, elseBranch: ElseBranch = None, label: str = None):
		super().__init__(label)

		self._ifBranch = ifBranch
		ifBranch._parent = self

		self._elsifBranches = []
		if elsifBranches is not None:
			for branch in elsifBranches:
				self._elsifBranches.append(branch)
				branch._parent = self

		if elseBranch is not None:
			self._elseBranch = elseBranch
			elseBranch._parent = self
		else:
			self._elseBranch = None

	@property
	def IfBranch(self) -> IfBranch:
		return self._ifBranch

	@property
	def ElsIfBranches(self) -> List['ElsifBranch']:
		return self._elsifBranches

	@property
	def ElseBranch(self) -> Nullable[ElseBranch]:
		return self._elseBranch


@export
class SequentialChoice(BaseChoice):
	"""A ``SequentialChoice`` is a base-class for all sequential choices (in case statements)."""


@export
class IndexedChoice(SequentialChoice):
	_expression: ExpressionUnion

	def __init__(self, expression: ExpressionUnion):
		super().__init__()

		self._expression = expression
		# expression._parent = self    # FIXME: received None

	@property
	def Expression(self) -> ExpressionUnion:
		return self._expression

[docs] def __str__(self) -> str: return str(self._expression)
@export class RangedChoice(SequentialChoice): _range: 'Range' def __init__(self, rng: 'Range'): super().__init__() self._range = rng rng._parent = self @property def Range(self) -> 'Range': return self._range
[docs] def __str__(self) -> str: return str(self._range)
@export class SequentialCase(BaseCase, SequentialStatements): _choices: List def __init__(self, statements: Iterable[SequentialStatement] = None): super().__init__() SequentialStatements.__init__(self, statements) # TODO: what about choices? @property def Choices(self) -> List[BaseChoice]: return self._choices @export class Case(SequentialCase): _choices: List[SequentialChoice] def __init__(self, choices: Iterable[SequentialChoice], statements: Iterable[SequentialStatement] = None): super().__init__(statements) self._choices = [] if choices is not None: for choice in choices: self._choices.append(choice) choice._parent = self @property def Choices(self) -> List[SequentialChoice]: return self._choices
[docs] def __str__(self) -> str: return "when {choices} =>".format(choices=" | ".join(str(c) for c in self._choices))
@export class OthersCase(SequentialCase):
[docs] def __str__(self) -> str: return "when others =>"
@export class CaseStatement(CompoundStatement): _expression: ExpressionUnion _cases: List[SequentialCase] def __init__(self, expression: ExpressionUnion, cases: Iterable[SequentialCase], label: str = None): super().__init__(label) self._expression = expression expression._parent = self self._cases = [] if cases is not None: for case in cases: self._cases.append(case) case._parent = self @property def SelectExpression(self) -> ExpressionUnion: return self._expression @property def Cases(self) -> List[SequentialCase]: return self._cases @export class LoopStatement(CompoundStatement, SequentialStatements): """A ``LoopStatement`` is a base-class for all loop statements.""" def __init__(self, statements: Iterable[SequentialStatement] = None, label: str = None): super().__init__(label) SequentialStatements.__init__(self, statements) @export class EndlessLoopStatement(LoopStatement): pass @export class ForLoopStatement(LoopStatement): _loopIndex: str _range: Range def __init__(self, loopIndex: str, rng: Range, statements: Iterable[SequentialStatement] = None, label: str = None): super().__init__(statements, label) self._loopIndex = loopIndex self._range = rng rng._parent = self @property def LoopIndex(self) -> str: return self._loopIndex @property def Range(self) -> Range: return self._range @export class WhileLoopStatement(LoopStatement, ConditionalMixin): def __init__(self, condition: ExpressionUnion, statements: Iterable[SequentialStatement] = None, label: str = None): super().__init__(statements, label) ConditionalMixin.__init__(self, condition) @export class LoopControlStatement(SequentialStatement, ConditionalMixin): """A ``LoopControlStatement`` is a base-class for all loop controlling statements.""" _loopReference: LoopStatement def __init__(self, condition: ExpressionUnion = None, loopLabel: str = None): # TODO: is this label (currently str) a Name or a Label class? super().__init__() ConditionalMixin.__init__(self, condition) # TODO: loopLabel # TODO: loop reference -> is it a symbol? @property def LoopReference(self) -> LoopStatement: return self._loopReference @export class NextStatement(LoopControlStatement): pass @export class ExitStatement(LoopControlStatement): pass @export class NullStatement(SequentialStatement): pass @export class ReturnStatement(SequentialStatement, ConditionalMixin): _returnValue: ExpressionUnion def __init__(self, returnValue: ExpressionUnion = None): super().__init__() ConditionalMixin.__init__(self, returnValue) # TODO: return value? @property def ReturnValue(self) -> ExpressionUnion: return self._returnValue @export class WaitStatement(SequentialStatement, ConditionalMixin): _sensitivityList: Nullable[List[Symbol]] _timeout: ExpressionUnion def __init__(self, sensitivityList: Iterable[Symbol] = None, condition: ExpressionUnion = None, timeout: ExpressionUnion = None, label: str = None): super().__init__(label) ConditionalMixin.__init__(self, condition) if sensitivityList is None: self._sensitivityList = None else: self._sensitivityList = [] # TODO: convert to dict for signalSymbol in sensitivityList: self._sensitivityList.append(signalSymbol) signalSymbol._parent = self self._timeout = timeout if timeout is not None: timeout._parent = self @property def SensitivityList(self) -> List[Symbol]: return self._sensitivityList @property def Timeout(self) -> ExpressionUnion: return self._timeout @export class SequentialDeclarations: _declaredItems: List def __init__(self, declaredItems: Iterable): # TODO: extract to mixin self._declaredItems = [] # TODO: convert to dict if declaredItems is not None: for item in declaredItems: self._declaredItems.append(item) item._parent = self @property def DeclaredItems(self) -> List: return self._declaredItems