aboutsummaryrefslogtreecommitdiffstats
path: root/pyGHDL/dom/Sequential.py
diff options
context:
space:
mode:
Diffstat (limited to 'pyGHDL/dom/Sequential.py')
-rw-r--r--pyGHDL/dom/Sequential.py388
1 files changed, 388 insertions, 0 deletions
diff --git a/pyGHDL/dom/Sequential.py b/pyGHDL/dom/Sequential.py
new file mode 100644
index 000000000..896b09544
--- /dev/null
+++ b/pyGHDL/dom/Sequential.py
@@ -0,0 +1,388 @@
+# =============================================================================
+# ____ _ _ ____ _ _
+# _ __ _ _ / ___| | | | _ \| | __| | ___ _ __ ___
+# | '_ \| | | | | _| |_| | | | | | / _` |/ _ \| '_ ` _ \
+# | |_) | |_| | |_| | _ | |_| | |___ | (_| | (_) | | | | | |
+# | .__/ \__, |\____|_| |_|____/|_____(_)__,_|\___/|_| |_| |_|
+# |_| |___/
+# =============================================================================
+# Authors:
+# Patrick Lehmann
+#
+# Package module: DOM: Sequential statements.
+#
+# License:
+# ============================================================================
+# Copyright (C) 2019-2021 Tristan Gingold
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <gnu.org/licenses>.
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+# ============================================================================
+from typing import Iterable
+
+from pydecor import export
+
+from pyGHDL.dom.Concurrent import WaveformElement # TODO: move out from concurrent?
+from pyGHDL.dom.Range import Range
+from pyVHDLModel.SyntaxModel import (
+ IfBranch as VHDLModel_IfBranch,
+ ElsifBranch as VHDLModel_ElsifBranch,
+ ElseBranch as VHDLModel_ElseBranch,
+ IfStatement as VHDLModel_IfStatement,
+ IndexedChoice as VHDLModel_IndexedChoice,
+ RangedChoice as VHDLModel_RangedChoice,
+ OthersCase as VHDLModel_OthersCase,
+ Case as VHDLModel_Case,
+ CaseStatement as VHDLModel_CaseStatement,
+ ForLoopStatement as VHDLModel_ForLoopStatement,
+ SequentialSimpleSignalAssignment as VHDLModel_SequentialSimpleSignalAssignment,
+ SequentialProcedureCall as VHDLModel_SequentialProcedureCall,
+ Name,
+ SequentialStatement,
+ Expression,
+ SequentialChoice, SequentialCase,
+)
+
+
+from pyGHDL.libghdl import Iir, utils
+from pyGHDL.libghdl.vhdl import nodes
+from pyGHDL.dom import DOMMixin
+from pyGHDL.dom._Utils import GetNameOfNode
+
+
+@export
+class IfBranch(VHDLModel_IfBranch):
+ def __init__(
+ self,
+ branchNode: Iir,
+ condition: Expression,
+ statements: Iterable[SequentialStatement] = None,
+ ):
+ super().__init__(condition, statements)
+ DOMMixin.__init__(self, branchNode)
+
+ @classmethod
+ def parse(cls, generateNode: Iir, label: str) -> "IfBranch":
+ from pyGHDL.dom._Translate import (
+ GetSequentialStatementsFromChainedNodes,
+ GetExpressionFromNode,
+ )
+
+ condition = GetExpressionFromNode(nodes.Get_Condition(generateNode))
+ body = nodes.Get_Generate_Statement_Body(generateNode)
+
+ statementChain = nodes.Get_Sequential_Statement_Chain(body)
+ statements = GetSequentialStatementsFromChainedNodes(
+ statementChain, "if branch", label
+ )
+
+ return cls(generateNode, condition, statements)
+
+
+@export
+class ElsifBranch(VHDLModel_ElsifBranch):
+ def __init__(
+ self,
+ branchNode: Iir,
+ condition: Expression,
+ statements: Iterable[SequentialStatement] = None,
+ ):
+ super().__init__(condition, statements)
+ DOMMixin.__init__(self, branchNode)
+
+ @classmethod
+ def parse(cls, generateNode: Iir, condition: Iir, label: str) -> "ElsifBranch":
+ from pyGHDL.dom._Translate import (
+ GetSequentialStatementsFromChainedNodes,
+ GetExpressionFromNode,
+ )
+
+ condition = GetExpressionFromNode(condition)
+ body = nodes.Get_Generate_Statement_Body(generateNode)
+
+ statementChain = nodes.Get_Sequential_Statement_Chain(body)
+ statements = GetSequentialStatementsFromChainedNodes(
+ statementChain, "elsif branch", label
+ )
+
+ return cls(generateNode, condition, statements)
+
+
+@export
+class ElseBranch(VHDLModel_ElseBranch):
+ def __init__(
+ self,
+ branchNode: Iir,
+ statements: Iterable[SequentialStatement] = None,
+ ):
+ super().__init__(statements)
+ DOMMixin.__init__(self, branchNode)
+
+ @classmethod
+ def parse(cls, generateNode: Iir, label: str) -> "ElseBranch":
+ from pyGHDL.dom._Translate import (
+ GetSequentialStatementsFromChainedNodes,
+ )
+
+ body = nodes.Get_Generate_Statement_Body(generateNode)
+
+ statementChain = nodes.Get_Sequential_Statement_Chain(body)
+ statements = GetSequentialStatementsFromChainedNodes(
+ statementChain, "else branch", label
+ )
+
+ return cls(generateNode, statements)
+
+
+@export
+class IfStatement(VHDLModel_IfStatement, DOMMixin):
+ def __init__(
+ self,
+ generateNode: Iir,
+ ifBranch: IfBranch,
+ elsifBranches: Iterable[ElsifBranch] = None,
+ elseBranch: ElseBranch = None,
+ label: str = None,
+ ):
+ super().__init__(ifBranch, elsifBranches, elseBranch, label)
+ DOMMixin.__init__(self, generateNode)
+
+ @classmethod
+ def parse(cls, generateNode: Iir, label: str) -> "IfStatement":
+ ifBranch = IfBranch.parse(generateNode, label)
+ elsifBranches = []
+ elseBranch = None
+ # WORKAROUND: Python 3.8 syntax
+ # elseClause = generateNode
+ # while (elseClause := nodes.Get_Generate_Else_Clause(elseClause)) != nodes.Null_Iir:
+ elseClause = nodes.Get_Generate_Else_Clause(generateNode)
+ while elseClause != nodes.Null_Iir:
+ condition = nodes.Get_Condition(elseClause)
+ if condition != nodes.Null_Iir:
+ elsifBranches.append(ElsifBranch.parse(elseClause, condition, label))
+ else:
+ elseBranch = ElseBranch.parse(elseClause, label)
+ break
+
+ elseClause = nodes.Get_Generate_Else_Clause(elseClause)
+
+ return cls(generateNode, ifBranch, elsifBranches, elseBranch, label)
+
+
+@export
+class IndexedChoice(VHDLModel_IndexedChoice, DOMMixin):
+ def __init__(self, node: Iir, expression: Expression):
+ super().__init__(expression)
+ DOMMixin.__init__(self, node)
+
+
+@export
+class RangedChoice(VHDLModel_RangedChoice, DOMMixin):
+ def __init__(self, node: Iir, rng: Range):
+ super().__init__(rng)
+ DOMMixin.__init__(self, node)
+
+
+@export
+class Case(VHDLModel_Case, DOMMixin):
+ def __init__(self, node: Iir, choices: Iterable[SequentialChoice], statements: Iterable[SequentialStatement]):
+ super().__init__(choices, statements)
+ DOMMixin.__init__(self, node)
+
+ @classmethod
+ def parse(cls, caseNode: Iir, label: str) -> "Case":
+ from pyGHDL.dom._Translate import (
+ GetSequentialStatementsFromChainedNodes,
+ )
+
+ body = nodes.Get_Generate_Statement_Body(caseNode)
+
+ statementChain = nodes.Get_Sequential_Statement_Chain(body)
+ statements = GetSequentialStatementsFromChainedNodes(
+ statementChain, "case", label
+ )
+
+ choices = []
+
+ return cls(caseNode, choices, statements)
+
+
+@export
+class OthersCase(VHDLModel_OthersCase, DOMMixin):
+ def __init__(
+ self,
+ caseNode: Iir,
+ statements: Iterable[SequentialStatement] = None,
+ ):
+ super().__init__(statements)
+ DOMMixin.__init__(self, caseNode)
+
+ @classmethod
+ def parse(cls, caseNode: Iir) -> "OthersCase":
+ from pyGHDL.dom._Translate import (
+ GetDeclaredItemsFromChainedNodes,
+ GetSequentialStatementsFromChainedNodes,
+ )
+
+ # body = nodes.Get_Generate_Statement_Body(caseNode)
+ #
+ # statementChain = nodes.Get_Sequential_Statement_Chain(body)
+ # statements = GetStatementsFromChainedNodes(
+ # statementChain, "else branch", alternativeLabel
+ # )
+
+ # return cls(caseNode, declaredItems, statements, alternativeLabel)
+ return cls(caseNode, [], [], "")
+
+
+@export
+class CaseStatement(VHDLModel_CaseStatement, DOMMixin):
+ def __init__(
+ self, generateNode: Iir, label: str, expression: Expression, cases: Iterable[SequentialCase]
+ ):
+ super().__init__(expression, cases, label)
+ DOMMixin.__init__(self, generateNode)
+
+ @classmethod
+ def parse(cls, generateNode: Iir, label: str) -> "CaseStatement":
+ from pyGHDL.dom._Translate import (
+ GetExpressionFromNode,
+ GetIirKindOfNode,
+ GetRangeFromNode,
+ )
+
+ # TODO: get choices
+
+ expression = GetExpressionFromNode(nodes.Get_Expression(generateNode))
+
+ cases = []
+ choices = []
+ alternatives = nodes.Get_Case_Statement_Alternative_Chain(generateNode)
+ for alternative in utils.chain_iter(alternatives):
+ choiceKind = GetIirKindOfNode(alternative)
+
+ if choiceKind in (
+ nodes.Iir_Kind.Choice_By_Name,
+ nodes.Iir_Kind.Choice_By_Expression,
+ ):
+ choiceExpression = GetExpressionFromNode(
+ nodes.Get_Choice_Expression(alternative)
+ )
+ choices.append(IndexedChoice(alternative, choiceExpression))
+ cases.append(Case(alternative, choices))
+ choices = []
+ elif choiceKind is nodes.Iir_Kind.Choice_By_Range:
+ rng = GetRangeFromNode(nodes.Get_Choice_Range(alternative))
+ choices.append(RangedChoice(alternative, rng))
+ cases.append(Case(alternative, choices))
+ choices = []
+ elif choiceKind is nodes.Iir_Kind.Choice_By_Others:
+ cases.append(OthersCase.parse(alternative))
+ else:
+ print(choiceKind)
+
+ return cls(generateNode, label, expression, cases)
+
+
+@export
+class ForLoopStatement(VHDLModel_ForLoopStatement, DOMMixin):
+ def __init__(
+ self,
+ generateNode: Iir,
+ loopIndex: str,
+ range: Range,
+ statements: Iterable[SequentialStatement] = None,
+ label: str = None,
+ ):
+ super().__init__(loopIndex, range, statements, label)
+ DOMMixin.__init__(self, generateNode)
+
+ @classmethod
+ def parse(cls, generateNode: Iir, label: str) -> "ForLoopStatement":
+ from pyGHDL.dom._Translate import (
+ GetSequentialStatementsFromChainedNodes,
+ GetRangeFromNode,
+ )
+
+ spec = nodes.Get_Parameter_Specification(generateNode)
+ loopIndex = GetNameOfNode(spec)
+ rng = GetRangeFromNode(nodes.Get_Discrete_Range(spec))
+
+ body = nodes.Get_Generate_Statement_Body(generateNode)
+
+ statementChain = nodes.Get_Sequential_Statement_Chain(body)
+ statements = GetSequentialStatementsFromChainedNodes(
+ statementChain, "for", label
+ )
+
+ return cls(generateNode, loopIndex, rng, statements, label)
+
+
+@export
+class SequentialSimpleSignalAssignment(
+ VHDLModel_SequentialSimpleSignalAssignment, DOMMixin
+):
+ def __init__(
+ self,
+ assignmentNode: Iir,
+ target: Name,
+ waveform: Iterable[WaveformElement],
+ label: str = None,
+ ):
+ super().__init__(target, waveform, label)
+ DOMMixin.__init__(self, assignmentNode)
+
+ @classmethod
+ def parse(
+ cls, assignmentNode: Iir, label: str = None
+ ) -> "SequentialSimpleSignalAssignment":
+ from pyGHDL.dom._Translate import GetNameFromNode
+
+ target = nodes.Get_Target(assignmentNode)
+ targetName = GetNameFromNode(target)
+
+ waveform = nodes.Get_Waveform_Chain(assignmentNode)
+
+ # TODO: translate waveforms to series of "expressions".
+ expression = [None]
+
+ return cls(assignmentNode, targetName, expression, label)
+
+
+@export
+class SequentialProcedureCall(VHDLModel_SequentialProcedureCall, DOMMixin):
+ def __init__(
+ self,
+ callNode: Iir,
+ label: str,
+ procedureName: Name,
+ parameterMappings: Iterable,
+ ):
+ super().__init__(label, procedureName, parameterMappings)
+ DOMMixin.__init__(self, callNode)
+
+ @classmethod
+ def parse(cls, callNode: Iir, label: str) -> "SequentialProcedureCall":
+ from pyGHDL.dom._Translate import GetNameFromNode, GetIirKindOfNode
+
+ call = nodes.Get_Procedure_Call(callNode)
+ prefix = nodes.Get_Prefix(call)
+
+ procedureName = GetNameFromNode(prefix)
+
+ # TODO: parameter mappings
+ parameterMappings = []
+
+ return cls(callNode, label, procedureName, parameterMappings)