diff options
author | Patrick Lehmann <Patrick.Lehmann@plc2.de> | 2021-06-17 13:11:32 +0200 |
---|---|---|
committer | tgingold <tgingold@users.noreply.github.com> | 2021-06-17 21:34:16 +0200 |
commit | 4ec5cdcd77aa1b6fc384197e1208061d62f16ba2 (patch) | |
tree | 3c386d35b39b001db4e128abda379ddeb5ba7b2c /pyGHDL/dom | |
parent | 1eea725dedae1fe3eee47c2b4bfc18c7ac35e806 (diff) | |
download | ghdl-4ec5cdcd77aa1b6fc384197e1208061d62f16ba2.tar.gz ghdl-4ec5cdcd77aa1b6fc384197e1208061d62f16ba2.tar.bz2 ghdl-4ec5cdcd77aa1b6fc384197e1208061d62f16ba2.zip |
Updates to the dom namespace in pyGHDL.
Diffstat (limited to 'pyGHDL/dom')
-rw-r--r-- | pyGHDL/dom/Common.py | 57 | ||||
-rw-r--r-- | pyGHDL/dom/DesignUnit.py | 114 | ||||
-rw-r--r-- | pyGHDL/dom/Expression.py | 287 | ||||
-rw-r--r-- | pyGHDL/dom/InterfaceItem.py | 56 | ||||
-rw-r--r-- | pyGHDL/dom/Literal.py | 55 | ||||
-rw-r--r-- | pyGHDL/dom/Misc.py | 86 | ||||
-rw-r--r-- | pyGHDL/dom/Object.py | 72 | ||||
-rw-r--r-- | pyGHDL/dom/Range.py | 58 | ||||
-rw-r--r-- | pyGHDL/dom/Symbol.py | 60 | ||||
-rw-r--r-- | pyGHDL/dom/_Translate.py | 208 | ||||
-rw-r--r-- | pyGHDL/dom/_Utils.py | 38 | ||||
-rw-r--r-- | pyGHDL/dom/__init__.py | 20 | ||||
-rw-r--r-- | pyGHDL/dom/formatting/__init__.py | 0 | ||||
-rw-r--r-- | pyGHDL/dom/formatting/prettyprint.py | 296 |
14 files changed, 1239 insertions, 168 deletions
diff --git a/pyGHDL/dom/Common.py b/pyGHDL/dom/Common.py index 646e074e5..88d0cdc8c 100644 --- a/pyGHDL/dom/Common.py +++ b/pyGHDL/dom/Common.py @@ -1,19 +1,19 @@ # ============================================================================= -# ____ _ _ ____ _ _ -# _ __ _ _ / ___| | | | _ \| | __| | ___ _ __ ___ -# | '_ \| | | | | _| |_| | | | | | / _` |/ _ \| '_ ` _ \ -# | |_) | |_| | |_| | _ | |_| | |___ | (_| | (_) | | | | | | -# | .__/ \__, |\____|_| |_|____/|_____(_)__,_|\___/|_| |_| |_| -# |_| |___/ +# ____ _ _ ____ _ _ +# _ __ _ _ / ___| | | | _ \| | __| | ___ _ __ ___ +# | '_ \| | | | | _| |_| | | | | | / _` |/ _ \| '_ ` _ \ +# | |_) | |_| | |_| | _ | |_| | |___ | (_| | (_) | | | | | | +# | .__/ \__, |\____|_| |_|____/|_____(_)__,_|\___/|_| |_| |_| +# |_| |___/ # ============================================================================= -# Authors: -# Patrick Lehmann +# Authors: +# Patrick Lehmann # # Package module: DOM: Common classes for package pyGHDL.dom. # # License: # ============================================================================ -# Copyright (C) 2019-2020 Tristan Gingold +# 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 @@ -37,21 +37,14 @@ """ from pydecor import export -from pyVHDLModel.VHDLModel import Mode - -from pyGHDL.libghdl import name_table -from pyGHDL.libghdl.vhdl import nodes +from pyGHDL import GHDLBaseException +from pyGHDL.libghdl import LibGHDLException, errorout_memory __all__ = [] @export -class GHDLBaseException(Exception): - pass - - -@export -class LibGHDLException(GHDLBaseException): +class DOMException(GHDLBaseException): pass @@ -62,23 +55,11 @@ class GHDLException(GHDLBaseException): @export class GHDLMixin: - _MODE_TRANSLATION = { - nodes.Iir_Mode.In_Mode: Mode.In, - nodes.Iir_Mode.Out_Mode: Mode.Out, - nodes.Iir_Mode.Inout_Mode: Mode.InOut, - nodes.Iir_Mode.Buffer_Mode: Mode.Buffer, - nodes.Iir_Mode.Linkage_Mode: Mode.Linkage, - } - - @classmethod - def _ghdlNodeToName(cls, node) -> str: - """Return the python string from node :obj:`node` identifier""" - return name_table.Get_Name_Ptr(nodes.Get_Identifier(node)) + def CheckForErrors(self) -> None: + errorCount = errorout_memory.Get_Nbr_Messages() + if errorCount != 0: + for i in range(errorCount): + print(errorout_memory.Get_Error_Message(i + 1)) - @classmethod - def _ghdlPortToMode(cls, port): - """Return the mode of a :obj:`port`.""" - try: - return cls._MODE_TRANSLATION[nodes.Get_Mode(port)] - except KeyError: - raise LibGHDLException("Unknown mode.") + raise DOMException("Error in libghdl.") \ + from LibGHDLException("libghdl: Internal error 2.") diff --git a/pyGHDL/dom/DesignUnit.py b/pyGHDL/dom/DesignUnit.py index 4cf1ac2ad..9827cec24 100644 --- a/pyGHDL/dom/DesignUnit.py +++ b/pyGHDL/dom/DesignUnit.py @@ -1,19 +1,19 @@ # ============================================================================= -# ____ _ _ ____ _ _ -# _ __ _ _ / ___| | | | _ \| | __| | ___ _ __ ___ -# | '_ \| | | | | _| |_| | | | | | / _` |/ _ \| '_ ` _ \ -# | |_) | |_| | |_| | _ | |_| | |___ | (_| | (_) | | | | | | -# | .__/ \__, |\____|_| |_|____/|_____(_)__,_|\___/|_| |_| |_| -# |_| |___/ +# ____ _ _ ____ _ _ +# _ __ _ _ / ___| | | | _ \| | __| | ___ _ __ ___ +# | '_ \| | | | | _| |_| | | | | | / _` |/ _ \| '_ ` _ \ +# | |_) | |_| | |_| | _ | |_| | |___ | (_| | (_) | | | | | | +# | .__/ \__, |\____|_| |_|____/|_____(_)__,_|\___/|_| |_| |_| +# |_| |___/ # ============================================================================= -# Authors: -# Patrick Lehmann +# Authors: +# Patrick Lehmann # -# Package module: DOM: VHDL design units (e.g. entity or package). +# Package module: DOM: VHDL design units (e.g. context or package). # # License: # ============================================================================ -# Copyright (C) 2019-2020 Tristan Gingold +# 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 @@ -32,7 +32,7 @@ # ============================================================================ """ -This module contains all DOM classes for VHDL's design units (:class:`entity <Entity>`, +This module contains all DOM classes for VHDL's design units (:class:`context <Entity>`, :class:`architecture <Architecture>`, :class:`package <Package>`, :class:`package body <PackageBody>`, :class:`context <Context>` and :class:`configuration <Configuration>`. @@ -41,56 +41,43 @@ This module contains all DOM classes for VHDL's design units (:class:`entity <En """ from pydecor import export -from pyVHDLModel.VHDLModel import Entity as VHDLModel_Entity -from pyVHDLModel.VHDLModel import Architecture as VHDLModel_Architecture -from pyVHDLModel.VHDLModel import Package as VHDLModel_Package -from pyVHDLModel.VHDLModel import PackageBody as VHDLModel_PackageBody -from pyVHDLModel.VHDLModel import Context as VHDLModel_Context +from pyVHDLModel.VHDLModel import Entity as VHDLModel_Entity +from pyVHDLModel.VHDLModel import Architecture as VHDLModel_Architecture +from pyVHDLModel.VHDLModel import Package as VHDLModel_Package +from pyVHDLModel.VHDLModel import PackageBody as VHDLModel_PackageBody +from pyVHDLModel.VHDLModel import Context as VHDLModel_Context from pyVHDLModel.VHDLModel import Configuration as VHDLModel_Configuration +from pyGHDL.libghdl import utils from pyGHDL.libghdl.vhdl import nodes -import pyGHDL.libghdl.utils as pyutils -from pyGHDL.dom.Common import GHDLMixin -from pyGHDL.dom.InterfaceItem import ( - GenericConstantInterfaceItem, - PortSignalInterfaceItem, -) +from pyGHDL.dom._Utils import NodeToName, GetIirKindOfNode +from pyGHDL.dom._Translate import GetExpressionFromNode, GetSubtypeIndicationFromNode, GetGenericsFromChainedNodes, GetPortsFromChainedNodes, \ + GetDeclaredItemsFromChainedNodes +from pyGHDL.dom.Common import GHDLMixin, DOMException +from pyGHDL.dom.Object import Constant, Signal __all__ = [] @export class Entity(VHDLModel_Entity, GHDLMixin): + @classmethod def parse(cls, libraryUnit): - name = cls._ghdlNodeToName(libraryUnit) + name = NodeToName(libraryUnit) entity = cls(name) - cls.__parseGenerics(libraryUnit, entity) - cls.__parsePorts(libraryUnit, entity) - - return entity - - @classmethod - def __ghdlGetGenerics(cls, entity): - return pyutils.chain_iter(nodes.Get_Generic_Chain(entity)) + for generic in GetGenericsFromChainedNodes(nodes.Get_Generic_Chain(libraryUnit)): + entity.GenericItems.append(generic) - @classmethod - def __ghdlGetPorts(cls, entity): - return pyutils.chain_iter(nodes.Get_Port_Chain(entity)) + for port in GetPortsFromChainedNodes(nodes.Get_Port_Chain(libraryUnit)): + entity.PortItems.append(port) - @classmethod - def __parseGenerics(cls, libraryUnit, entity): - for generic in cls.__ghdlGetGenerics(libraryUnit): - genericConstant = GenericConstantInterfaceItem.parse(generic) - entity.GenericItems.append(genericConstant) + for item in GetDeclaredItemsFromChainedNodes(nodes.Get_Declaration_Chain(libraryUnit), "entity", name): + entity.DeclaredItems.append(item) - @classmethod - def __parsePorts(cls, libraryUnit, entity): - for port in cls.__ghdlGetPorts(libraryUnit): - signalPort = PortSignalInterfaceItem.parse(port) - entity.PortItems.append(signalPort) + return entity @export @@ -102,10 +89,15 @@ class Architecture(VHDLModel_Architecture, GHDLMixin): @classmethod def parse(cls, libraryUnit): - name = cls._ghdlNodeToName(libraryUnit) - entityName = cls._ghdlNodeToName(nodes.Get_Entity_Name(libraryUnit)) + name = NodeToName(libraryUnit) + entityName = NodeToName(nodes.Get_Entity_Name(libraryUnit)) - return cls(name, entityName) + architecture = cls(name, entityName) + + for item in GetDeclaredItemsFromChainedNodes(nodes.Get_Declaration_Chain(libraryUnit), "architecture", name): + architecture.DeclaredItems.append(item) + + return architecture def resolve(self): pass @@ -113,31 +105,47 @@ class Architecture(VHDLModel_Architecture, GHDLMixin): @export class Package(VHDLModel_Package, GHDLMixin): + @classmethod def parse(cls, libraryUnit): - name = cls._ghdlNodeToName(libraryUnit) - return cls(name) + name = NodeToName(libraryUnit) + + package = cls(name) + + for item in GetDeclaredItemsFromChainedNodes(nodes.Get_Declaration_Chain(libraryUnit), "package", name): + package.DeclaredItems.append(item) + + return package @export class PackageBody(VHDLModel_PackageBody, GHDLMixin): + @classmethod def parse(cls, libraryUnit): - name = cls._ghdlNodeToName(libraryUnit) - return cls(name) + name = NodeToName(libraryUnit) + + packageBody = cls(name) + + for item in GetDeclaredItemsFromChainedNodes(nodes.Get_Declaration_Chain(libraryUnit), "package body", name): + packageBody.DeclaredItems.append(item) + + return packageBody @export class Context(VHDLModel_Context, GHDLMixin): + @classmethod def parse(cls, libraryUnit): - name = cls._ghdlNodeToName(libraryUnit) + name = NodeToName(libraryUnit) return cls(name) @export class Configuration(VHDLModel_Configuration, GHDLMixin): + @classmethod def parse(cls, libraryUnit): - name = cls._ghdlNodeToName(libraryUnit) + name = NodeToName(libraryUnit) return cls(name) diff --git a/pyGHDL/dom/Expression.py b/pyGHDL/dom/Expression.py new file mode 100644 index 000000000..7f32e7d54 --- /dev/null +++ b/pyGHDL/dom/Expression.py @@ -0,0 +1,287 @@ +# ============================================================================= +# ____ _ _ ____ _ _ +# _ __ _ _ / ___| | | | _ \| | __| | ___ _ __ ___ +# | '_ \| | | | | _| |_| | | | | | / _` |/ _ \| '_ ` _ \ +# | |_) | |_| | |_| | _ | |_| | |___ | (_| | (_) | | | | | | +# | .__/ \__, |\____|_| |_|____/|_____(_)__,_|\___/|_| |_| |_| +# |_| |___/ +# ============================================================================= +# Authors: +# Patrick Lehmann +# +# Package module: DOM: Interface items (e.g. generic or port) +# +# 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 pydecor import export + +from pyVHDLModel.VHDLModel import \ + InverseExpression as VHDLModel_InverseExpression, \ + IdentityExpression as VHDLModel_IdentityExpression, \ + NegationExpression as VHDLModel_NegationExpression, \ + AbsoluteExpression as VHDLModel_AbsoluteExpression, \ + TypeConversion as VHDLModel_TypeConversion, \ + FunctionCall as VHDLModel_FunctionCall, \ + QualifiedExpression as VHDLModel_QualifiedExpression, \ + AdditionExpression as VHDLModel_AdditionExpression, \ + SubtractionExpression as VHDLModel_SubtractionExpression, \ + ConcatenationExpression as VHDLModel_ConcatenationExpression, \ + MultiplyExpression as VHDLModel_MultiplyExpression, \ + DivisionExpression as VHDLModel_DivisionExpression, \ + RemainderExpression as VHDLModel_RemainderExpression, \ + ModuloExpression as VHDLModel_ModuloExpression, \ + ExponentiationExpression as VHDLModel_ExponentiationExpression, \ + AndExpression as VHDLModel_AndExpression, \ + NandExpression as VHDLModel_NandExpression, \ + OrExpression as VHDLModel_OrExpression, \ + NorExpression as VHDLModel_NorExpression, \ + XorExpression as VHDLModel_XorExpression, \ + XnorExpression as VHDLModel_XnorExpression, \ + EqualExpression as VHDLModel_EqualExpression, \ + UnequalExpression as VHDLModel_UnequalExpression, \ + GreaterThanExpression as VHDLModel_GreaterThanExpression, \ + GreaterEqualExpression as VHDLModel_GreaterEqualExpression, \ + LessThanExpression as VHDLModel_LessThanExpression, \ + ShiftRightLogicExpression as VHDLModel_ShiftRightLogicExpression, \ + ShiftLeftLogicExpression as VHDLModel_ShiftLeftLogicExpression, \ + ShiftRightArithmeticExpression as VHDLModel_ShiftRightArithmeticExpression, \ + ShiftLeftArithmeticExpression as VHDLModel_ShiftLeftArithmeticExpression, \ + RotateRightExpression as VHDLModel_RotateRightExpression, \ + RotateLeftExpression as VHDLModel_RotateLeftExpression, \ + Expression + +__all__ = [] + +@export +class InverseExpression(VHDLModel_InverseExpression): + def __init__(self, operand: Expression): + super().__init__() + self._operand = operand + +@export +class IdentityExpression(VHDLModel_IdentityExpression): + def __init__(self, operand: Expression): + super().__init__() + self._operand = operand + +@export +class NegationExpression(VHDLModel_NegationExpression): + def __init__(self, operand: Expression): + super().__init__() + self._operand = operand + +@export +class AbsoluteExpression(VHDLModel_AbsoluteExpression): + def __init__(self, operand: Expression): + super().__init__() + self._operand = operand + +@export +class TypeConversion(VHDLModel_TypeConversion): + def __init__(self, operand: Expression): + super().__init__() + self._operand = operand + +@export +class FunctionCall(VHDLModel_FunctionCall): + def __init__(self, operand: Expression): + super().__init__() + self._operand = operand + +@export +class QualifiedExpression(VHDLModel_QualifiedExpression): + def __init__(self, operand: Expression): + super().__init__() + self._operand = operand + +@export +class AdditionExpression(VHDLModel_AdditionExpression): + def __init__(self, left: Expression, right: Expression): + super().__init__() + self._leftOperand = left + self._rightOperand = right + +@export +class SubtractionExpression(VHDLModel_SubtractionExpression): + def __init__(self, left: Expression, right: Expression): + super().__init__() + self._leftOperand = left + self._rightOperand = right + +@export +class ConcatenationExpression(VHDLModel_ConcatenationExpression): + def __init__(self, left: Expression, right: Expression): + super().__init__() + self._leftOperand = left + self._rightOperand = right + +@export +class MultiplyExpression(VHDLModel_MultiplyExpression): + def __init__(self, left: Expression, right: Expression): + super().__init__() + self._leftOperand = left + self._rightOperand = right + +@export +class DivisionExpression(VHDLModel_DivisionExpression): + def __init__(self, left: Expression, right: Expression): + super().__init__() + self._leftOperand = left + self._rightOperand = right + +@export +class RemainderExpression(VHDLModel_RemainderExpression): + def __init__(self, left: Expression, right: Expression): + super().__init__() + self._leftOperand = left + self._rightOperand = right + +@export +class ModuloExpression(VHDLModel_ModuloExpression): + def __init__(self, left: Expression, right: Expression): + super().__init__() + self._leftOperand = left + self._rightOperand = right + +@export +class ExponentiationExpression(VHDLModel_ExponentiationExpression): + def __init__(self, left: Expression, right: Expression): + super().__init__() + self._leftOperand = left + self._rightOperand = right + +@export +class AndExpression(VHDLModel_AndExpression): + def __init__(self, left: Expression, right: Expression): + super().__init__() + self._leftOperand = left + self._rightOperand = right + +@export +class NandExpression(VHDLModel_NandExpression): + def __init__(self, left: Expression, right: Expression): + super().__init__() + self._leftOperand = left + self._rightOperand = right + +@export +class OrExpression(VHDLModel_OrExpression): + def __init__(self, left: Expression, right: Expression): + super().__init__() + self._leftOperand = left + self._rightOperand = right + +@export +class NorExpression(VHDLModel_NorExpression): + def __init__(self, left: Expression, right: Expression): + super().__init__() + self._leftOperand = left + self._rightOperand = right + +@export +class XorExpression(VHDLModel_XorExpression): + def __init__(self, left: Expression, right: Expression): + super().__init__() + self._leftOperand = left + self._rightOperand = right + +@export +class XnorExpression(VHDLModel_XnorExpression): + def __init__(self, left: Expression, right: Expression): + super().__init__() + self._leftOperand = left + self._rightOperand = right + +@export +class EqualExpression(VHDLModel_EqualExpression): + def __init__(self, left: Expression, right: Expression): + super().__init__() + self._leftOperand = left + self._rightOperand = right + +@export +class UnequalExpression(VHDLModel_UnequalExpression): + def __init__(self, left: Expression, right: Expression): + super().__init__() + self._leftOperand = left + self._rightOperand = right + +@export +class GreaterThanExpression(VHDLModel_GreaterThanExpression): + def __init__(self, left: Expression, right: Expression): + super().__init__() + self._leftOperand = left + self._rightOperand = right + +@export +class GreaterEqualExpression(VHDLModel_GreaterEqualExpression): + def __init__(self, left: Expression, right: Expression): + super().__init__() + self._leftOperand = left + self._rightOperand = right + +@export +class LessThanExpression(VHDLModel_LessThanExpression): + def __init__(self, left: Expression, right: Expression): + super().__init__() + self._leftOperand = left + self._rightOperand = right + +@export +class ShiftRightLogicExpression(VHDLModel_ShiftRightLogicExpression): + def __init__(self, left: Expression, right: Expression): + super().__init__() + self._leftOperand = left + self._rightOperand = right + +@export +class ShiftLeftLogicExpression(VHDLModel_ShiftLeftLogicExpression): + def __init__(self, left: Expression, right: Expression): + super().__init__() + self._leftOperand = left + self._rightOperand = right + +@export +class ShiftRightArithmeticExpression(VHDLModel_ShiftRightArithmeticExpression): + def __init__(self, left: Expression, right: Expression): + super().__init__() + self._leftOperand = left + self._rightOperand = right + +@export +class ShiftLeftArithmeticExpression(VHDLModel_ShiftLeftArithmeticExpression): + def __init__(self, left: Expression, right: Expression): + super().__init__() + self._leftOperand = left + self._rightOperand = right + +@export +class RotateRightExpression(VHDLModel_RotateRightExpression): + def __init__(self, left: Expression, right: Expression): + super().__init__() + self._leftOperand = left + self._rightOperand = right + +@export +class RotateLeftExpression(VHDLModel_RotateLeftExpression): + def __init__(self, left: Expression, right: Expression): + super().__init__() + self._leftOperand = left + self._rightOperand = right diff --git a/pyGHDL/dom/InterfaceItem.py b/pyGHDL/dom/InterfaceItem.py index 0134655d5..89427e3b4 100644 --- a/pyGHDL/dom/InterfaceItem.py +++ b/pyGHDL/dom/InterfaceItem.py @@ -1,19 +1,19 @@ # ============================================================================= -# ____ _ _ ____ _ _ -# _ __ _ _ / ___| | | | _ \| | __| | ___ _ __ ___ -# | '_ \| | | | | _| |_| | | | | | / _` |/ _ \| '_ ` _ \ -# | |_) | |_| | |_| | _ | |_| | |___ | (_| | (_) | | | | | | -# | .__/ \__, |\____|_| |_|____/|_____(_)__,_|\___/|_| |_| |_| -# |_| |___/ +# ____ _ _ ____ _ _ +# _ __ _ _ / ___| | | | _ \| | __| | ___ _ __ ___ +# | '_ \| | | | | _| |_| | | | | | / _` |/ _ \| '_ ` _ \ +# | |_) | |_| | |_| | _ | |_| | |___ | (_| | (_) | | | | | | +# | .__/ \__, |\____|_| |_|____/|_____(_)__,_|\___/|_| |_| |_| +# |_| |___/ # ============================================================================= -# Authors: -# Patrick Lehmann +# Authors: +# Patrick Lehmann # # Package module: DOM: Interface items (e.g. generic or port) # # License: # ============================================================================ -# Copyright (C) 2019-2020 Tristan Gingold +# 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 @@ -30,17 +30,16 @@ # # SPDX-License-Identifier: GPL-2.0-or-later # ============================================================================ - from pydecor import export -from pyVHDLModel.VHDLModel import ( - PortSignalInterfaceItem as VHDLModel_PortSignalInterfaceItem, -) -from pyVHDLModel.VHDLModel import ( - GenericConstantInterfaceItem as VHDLModel_GenericConstantInterfaceItem, -) +from pyVHDLModel.VHDLModel import \ + GenericConstantInterfaceItem as VHDLModel_GenericConstantInterfaceItem, \ + PortSignalInterfaceItem as VHDLModel_PortSignalInterfaceItem, \ + Mode, SubTypeOrSymbol, Expression -from pyGHDL.dom.Common import GHDLMixin +from pyGHDL.dom._Utils import NodeToName, GetModeOfNode +from pyGHDL.dom._Translate import GetSubtypeIndicationFromNode +from pyGHDL.dom.Common import GHDLMixin __all__ = [] @@ -49,21 +48,32 @@ __all__ = [] class GenericConstantInterfaceItem(VHDLModel_GenericConstantInterfaceItem, GHDLMixin): @classmethod def parse(cls, generic): - name = cls._ghdlNodeToName(generic) - mode = cls._ghdlPortToMode(generic) + name = NodeToName(generic) + mode = GetModeOfNode(generic) + subTypeIndication = GetSubtypeIndicationFromNode(generic, "generic", name) - generic = cls(name, mode) + generic = cls(name, mode, subTypeIndication) return generic + def __init__(self, name:str, mode: Mode, subType: SubTypeOrSymbol): + super().__init__(name=name, mode=mode) + self._subType = subType @export class PortSignalInterfaceItem(VHDLModel_PortSignalInterfaceItem, GHDLMixin): @classmethod def parse(cls, port): - name = cls._ghdlNodeToName(port) - mode = cls._ghdlPortToMode(port) + name = NodeToName(port) + mode = GetModeOfNode(port) + subTypeIndication = GetSubtypeIndicationFromNode(port, "port", name) - port = cls(name, mode) + port = cls(name, mode, subTypeIndication) return port + + def __init__(self, name:str, mode: Mode, subType: SubTypeOrSymbol, defaultExpression: Expression = None): + super().__init__(name=name, mode=mode) + self._subType = subType + self._defaultExpression = defaultExpression + diff --git a/pyGHDL/dom/Literal.py b/pyGHDL/dom/Literal.py new file mode 100644 index 000000000..2ed1b5f65 --- /dev/null +++ b/pyGHDL/dom/Literal.py @@ -0,0 +1,55 @@ +# ============================================================================= +# ____ _ _ ____ _ _ +# _ __ _ _ / ___| | | | _ \| | __| | ___ _ __ ___ +# | '_ \| | | | | _| |_| | | | | | / _` |/ _ \| '_ ` _ \ +# | |_) | |_| | |_| | _ | |_| | |___ | (_| | (_) | | | | | | +# | .__/ \__, |\____|_| |_|____/|_____(_)__,_|\___/|_| |_| |_| +# |_| |___/ +# ============================================================================= +# Authors: +# Patrick Lehmann +# +# Package module: DOM: Interface items (e.g. generic or port) +# +# 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 pydecor import export + +from pyVHDLModel.VHDLModel import \ + IntegerLiteral as VHDLModel_IntegerLiteral, \ + FloatingPointLiteral as VHDLModel_FloatingPointLiteral, \ + CharacterLiteral as VHDLModel_CharacterLiteral + +__all__ = [] + + +@export +class IntegerLiteral(VHDLModel_IntegerLiteral): + pass + + +@export +class FloatingPointLiteral(VHDLModel_FloatingPointLiteral): + pass + + +@export +class CharacterLiteral(VHDLModel_CharacterLiteral): + pass diff --git a/pyGHDL/dom/Misc.py b/pyGHDL/dom/Misc.py index 43c201c46..0f26119a2 100644 --- a/pyGHDL/dom/Misc.py +++ b/pyGHDL/dom/Misc.py @@ -1,19 +1,19 @@ # ============================================================================= -# ____ _ _ ____ _ _ -# _ __ _ _ / ___| | | | _ \| | __| | ___ _ __ ___ -# | '_ \| | | | | _| |_| | | | | | / _` |/ _ \| '_ ` _ \ -# | |_) | |_| | |_| | _ | |_| | |___ | (_| | (_) | | | | | | -# | .__/ \__, |\____|_| |_|____/|_____(_)__,_|\___/|_| |_| |_| -# |_| |___/ +# ____ _ _ ____ _ _ +# _ __ _ _ / ___| | | | _ \| | __| | ___ _ __ ___ +# | '_ \| | | | | _| |_| | | | | | / _` |/ _ \| '_ ` _ \ +# | |_) | |_| | |_| | _ | |_| | |___ | (_| | (_) | | | | | | +# | .__/ \__, |\____|_| |_|____/|_____(_)__,_|\___/|_| |_| |_| +# |_| |___/ # ============================================================================= -# Authors: -# Patrick Lehmann +# Authors: +# Patrick Lehmann # # Package module: DOM: Elements not covered by the VHDL standard. # # License: # ============================================================================ -# Copyright (C) 2019-2020 Tristan Gingold +# 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 @@ -36,27 +36,22 @@ Add a module documentation. """ from pathlib import Path -from typing import Any +from typing import Any +import pyGHDL.libghdl.utils from pydecor import export -from pyVHDLModel.VHDLModel import Design as VHDLModel_Design -from pyVHDLModel.VHDLModel import Library as VHDLModel_Library -from pyVHDLModel.VHDLModel import Document as VHDLModel_Document +from pyGHDL.dom._Utils import GetIirKindOfNode +from pyVHDLModel.VHDLModel import Design as VHDLModel_Design +from pyVHDLModel.VHDLModel import Library as VHDLModel_Library +from pyVHDLModel.VHDLModel import Document as VHDLModel_Document -import pyGHDL.libghdl as libghdl -from pyGHDL.libghdl import name_table, files_map, errorout_memory -from pyGHDL.libghdl.vhdl import nodes, sem_lib +import pyGHDL.libghdl as libghdl +from pyGHDL.libghdl import name_table, files_map, errorout_memory, LibGHDLException, utils +from pyGHDL.libghdl.vhdl import nodes, sem_lib -from pyGHDL.dom.Common import LibGHDLException, GHDLException -from pyGHDL.dom.DesignUnit import ( - Entity, - Architecture, - Package, - PackageBody, - Context, - Configuration, -) +from pyGHDL.dom.Common import DOMException, GHDLMixin +from pyGHDL.dom.DesignUnit import Entity, Architecture, Package, PackageBody, Context, Configuration __all__ = [] @@ -90,61 +85,66 @@ class Library(VHDLModel_Library): @export -class Document(VHDLModel_Document): +class Document(VHDLModel_Document, GHDLMixin): __ghdlFileID: Any __ghdlSourceFileEntry: Any __ghdlFile: Any def __init__(self, path: Path = None, dontParse: bool = False): super().__init__(path) + GHDLMixin.__init__(self) self.__ghdl_init() - if dontParse == False: + if (dontParse == False): self.parse() def __ghdl_init(self): # Read input file self.__ghdlFileID = name_table.Get_Identifier(str(self.Path)) - self.__ghdlSourceFileEntry = files_map.Read_Source_File( - name_table.Null_Identifier, self.__ghdlFileID - ) + self.__ghdlSourceFileEntry = files_map.Read_Source_File(name_table.Null_Identifier, self.__ghdlFileID) if self.__ghdlSourceFileEntry == files_map.No_Source_File_Entry: raise LibGHDLException("Cannot load file '{!s}'".format(self.Path)) - # parse + self.CheckForErrors() + + # Parse input file self.__ghdlFile = sem_lib.Load_File(self.__ghdlSourceFileEntry) + self.CheckForErrors() + def parse(self): - unit = nodes.Get_First_Design_Unit(self.__ghdlFile) - while unit != nodes.Null_Iir: + firstUnit = nodes.Get_First_Design_Unit(self.__ghdlFile) + + for unit in utils.chain_iter(firstUnit): libraryUnit = nodes.Get_Library_Unit(unit) - nodeKind = nodes.Get_Kind(libraryUnit) + nodeKind = GetIirKindOfNode(libraryUnit) - if nodeKind == nodes.Iir_Kind.Entity_Declaration: + if (nodeKind == nodes.Iir_Kind.Entity_Declaration): entity = Entity.parse(libraryUnit) self.Entities.append(entity) - elif nodeKind == nodes.Iir_Kind.Architecture_Body: + elif (nodeKind == nodes.Iir_Kind.Architecture_Body): architecture = Architecture.parse(libraryUnit) self.Architectures.append(architecture) - elif nodeKind == nodes.Iir_Kind.Package_Declaration: + elif (nodeKind == nodes.Iir_Kind.Package_Declaration): package = Package.parse(libraryUnit) self.Packages.append(package) - elif nodeKind == nodes.Iir_Kind.Package_Body: + elif (nodeKind == nodes.Iir_Kind.Package_Body): packageBody = PackageBody.parse(libraryUnit) self.PackageBodies.append(packageBody) - elif nodeKind == nodes.Iir_Kind.Context_Declaration: + elif (nodeKind == nodes.Iir_Kind.Context_Declaration): context = Context.parse(libraryUnit) self.Contexts.append(context) - elif nodeKind == nodes.Iir_Kind.Configuration_Declaration: + elif (nodeKind == nodes.Iir_Kind.Configuration_Declaration): configuration = Configuration.parse(libraryUnit) self.Configurations.append(configuration) else: - raise GHDLException("Unknown design unit kind.") - - unit = nodes.Get_Chain(unit) + raise DOMException( + "Unknown design unit kind '{kindName}'({kind}).".format( + kindName=nodeKind.name, kind=nodeKind) + ) diff --git a/pyGHDL/dom/Object.py b/pyGHDL/dom/Object.py new file mode 100644 index 000000000..924c28662 --- /dev/null +++ b/pyGHDL/dom/Object.py @@ -0,0 +1,72 @@ +# ============================================================================= +# ____ _ _ ____ _ _ +# _ __ _ _ / ___| | | | _ \| | __| | ___ _ __ ___ +# | '_ \| | | | | _| |_| | | | | | / _` |/ _ \| '_ ` _ \ +# | |_) | |_| | |_| | _ | |_| | |___ | (_| | (_) | | | | | | +# | .__/ \__, |\____|_| |_|____/|_____(_)__,_|\___/|_| |_| |_| +# |_| |___/ +# ============================================================================= +# Authors: +# Patrick Lehmann +# +# Package module: DOM: Interface items (e.g. generic or port) +# +# 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 pydecor import export + +from pyVHDLModel.VHDLModel import \ + Constant as VHDLModel_Constant, \ + Variable as VHDLModel_Variable, \ + Signal as VHDLModel_Signal, \ + Expression, SubTypeOrSymbol + +__all__ = [] + + +@export +class Constant(VHDLModel_Constant): + def __init__(self, name: str, subType: SubTypeOrSymbol, defaultExpression: Expression): + super().__init__(name) + + self._name = name + self._subType = subType + self._defaultExpression = defaultExpression + + +@export +class Variable(VHDLModel_Variable): + def __init__(self, name: str, subType: SubTypeOrSymbol, defaultExpression: Expression): + super().__init__(name) + + self._name = name + self._subType = subType + self._defaultExpression = defaultExpression + + +@export +class Signal(VHDLModel_Signal): + def __init__(self, name: str, subType: SubTypeOrSymbol, defaultExpression: Expression): + super().__init__(name) + + self._name = name + self._subType = subType + self._defaultExpression = defaultExpression + diff --git a/pyGHDL/dom/Range.py b/pyGHDL/dom/Range.py new file mode 100644 index 000000000..45675cd19 --- /dev/null +++ b/pyGHDL/dom/Range.py @@ -0,0 +1,58 @@ +# ============================================================================= +# ____ _ _ ____ _ _ +# _ __ _ _ / ___| | | | _ \| | __| | ___ _ __ ___ +# | '_ \| | | | | _| |_| | | | | | / _` |/ _ \| '_ ` _ \ +# | |_) | |_| | |_| | _ | |_| | |___ | (_| | (_) | | | | | | +# | .__/ \__, |\____|_| |_|____/|_____(_)__,_|\___/|_| |_| |_| +# |_| |___/ +# ============================================================================= +# Authors: +# Patrick Lehmann +# +# Package module: DOM: Interface items (e.g. generic or port) +# +# 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 pydecor import export + +from pyVHDLModel.VHDLModel import \ + Range as VHDLModel_Range, \ + RangeExpression as VHDLModel_RangeExpression, \ + Direction, Expression + +__all__ = [] + + +@export +class Range(VHDLModel_Range): + def __init__(self, left: Expression, right: Expression, direction: Direction): + super().__init__() + + self._leftBound = left + self._rightBound = right + self._direction = direction + + +@export +class RangeExpression(VHDLModel_RangeExpression): + def __init__(self, range: Range): + super().__init__() + + self._range = range diff --git a/pyGHDL/dom/Symbol.py b/pyGHDL/dom/Symbol.py new file mode 100644 index 000000000..9b765872d --- /dev/null +++ b/pyGHDL/dom/Symbol.py @@ -0,0 +1,60 @@ +# ============================================================================= +# ____ _ _ ____ _ _ +# _ __ _ _ / ___| | | | _ \| | __| | ___ _ __ ___ +# | '_ \| | | | | _| |_| | | | | | / _` |/ _ \| '_ ` _ \ +# | |_) | |_| | |_| | _ | |_| | |___ | (_| | (_) | | | | | | +# | .__/ \__, |\____|_| |_|____/|_____(_)__,_|\___/|_| |_| |_| +# |_| |___/ +# ============================================================================= +# Authors: +# Patrick Lehmann +# +# Package module: DOM: Interface items (e.g. generic or port) +# +# 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 pydecor import export + +from typing import List + +from pyVHDLModel.VHDLModel import \ + SimpleSubTypeSymbol as VHDLModel_SimpleSubTypeSymbol, \ + ConstrainedSubTypeSymbol as VHDLModel_ConstrainedSubTypeSymbol, \ + SimpleObjectSymbol as VHDLModel_SimpleObjectSymbol, \ + Constraint + +__all__ = [] + + +@export +class SimpleSubTypeSymbol(VHDLModel_SimpleSubTypeSymbol): + def __init__(self, subTypeName: str): + super().__init__(subTypeName=subTypeName) + + +@export +class ConstrainedSubTypeSymbol(VHDLModel_ConstrainedSubTypeSymbol): + def __init__(self, subTypeName: str, constraints: List[Constraint] = None): + super().__init__(subTypeName=subTypeName, constraints=constraints) + +@export +class SimpleObjectSymbol(VHDLModel_SimpleObjectSymbol): + def __init__(self, symbolName: str): + super().__init__(symbolName) diff --git a/pyGHDL/dom/_Translate.py b/pyGHDL/dom/_Translate.py new file mode 100644 index 000000000..e93b20b07 --- /dev/null +++ b/pyGHDL/dom/_Translate.py @@ -0,0 +1,208 @@ +from typing import List + + +from pydecor import export +from pyVHDLModel.VHDLModel import Constraint, Direction, Expression, SubTypeOrSymbol + +from pyGHDL.libghdl import utils, name_table +from pyGHDL.libghdl.utils import flist_iter +from pyGHDL.libghdl.vhdl import nodes +from pyGHDL.dom._Utils import NodeToName, GetIirKindOfNode +from pyGHDL.dom.Common import DOMException +from pyGHDL.dom.Range import Range, RangeExpression +from pyGHDL.dom.Symbol import SimpleObjectSymbol, SimpleSubTypeSymbol, ConstrainedSubTypeSymbol +from pyGHDL.dom.Literal import IntegerLiteral, CharacterLiteral, FloatingPointLiteral +from pyGHDL.dom.Expression import SubtractionExpression, AdditionExpression, MultiplyExpression, DivisionExpression, InverseExpression, ExponentiationExpression + +__all__ = [] + + +@export +def GetSubtypeIndicationFromNode(node, entity: str, name: str) -> SubTypeOrSymbol: + subTypeIndication = nodes.Get_Subtype_Indication(node) + subTypeKind = GetIirKindOfNode(subTypeIndication) + + if (subTypeKind == nodes.Iir_Kind.Simple_Name): + subTypeName = NodeToName(subTypeIndication) + + subType = SimpleSubTypeSymbol(subTypeName) + elif (subTypeKind == nodes.Iir_Kind.Array_Subtype_Definition): + typeMark = nodes.Get_Subtype_Type_Mark(subTypeIndication) + typeMarkName = NodeToName(typeMark) + + constraints = GetArrayConstraintsFromSubtypeIndication(subTypeIndication) + subType = ConstrainedSubTypeSymbol(typeMarkName, constraints) + elif (subTypeKind == nodes.Iir_Kind.Subtype_Definition): + raise DOMException( + "Unknown handling of subtype kind '{kind}' of subtype indication '{indication}' while parsing {entity} '{name}'.".format( + kind=subTypeKind, indication=subTypeIndication, entity=entity, name=name) + ) + else: + raise DOMException( + "Unknown subtype kind '{kind}' of subtype indication '{indication}' while parsing {entity} '{name}'.".format( + kind=subTypeKind, indication=subTypeIndication, entity=entity, name=name) + ) + + return subType + +@export +def GetArrayConstraintsFromSubtypeIndication(subTypeIndication) -> List[Constraint]: + constraints = [] + for constraint in flist_iter(nodes.Get_Index_Constraint_List(subTypeIndication)): + constraintKind = GetIirKindOfNode(constraint) + if constraintKind == nodes.Iir_Kind.Range_Expression: + direction = nodes.Get_Direction(constraint) + leftBound = nodes.Get_Left_Limit_Expr(constraint) + rightBound = nodes.Get_Right_Limit_Expr(constraint) + + r = Range( + GetExpressionFromNode(leftBound), + GetExpressionFromNode(rightBound), + Direction.DownTo if direction else Direction.To + ) + constraints.append(RangeExpression(r)) + elif constraintKind == nodes.Iir_Kind.Attribute_Name: + raise DOMException("[NOT IMPLEMENTED] Attribute name as range.") + elif constraintKind == nodes.Iir_Kind.Simple_Name: + raise DOMException("[NOT IMPLEMENTED] Subtype as range.") + else: + raise DOMException( + "Unknown constraint kind '{kind}' for constraint '{constraint}' in subtype indication '{indication}'.".format( + kind=constraintKind, constraint=constraint, indication=subTypeIndication) + ) + + return constraints + + +@export +def GetExpressionFromNode(node) -> Expression: + kind = GetIirKindOfNode(node) + + if kind == nodes.Iir_Kind.Simple_Name: + name = NodeToName(node) + return SimpleObjectSymbol(name) + elif kind == nodes.Iir_Kind.Integer_Literal: + integerLiteralValue = nodes.Get_Value(node) + return IntegerLiteral(integerLiteralValue) + elif kind == nodes.Iir_Kind.Floating_Point_Literal: + fpLiteralValue = nodes.Get_Fp_Value(node) + return FloatingPointLiteral(fpLiteralValue) + elif kind == nodes.Iir_Kind.Character_Literal: + identifier = nodes.Get_Identifier(node) + characterLiteralValue = name_table.Get_Character(identifier) + return CharacterLiteral(characterLiteralValue) + elif kind == nodes.Iir_Kind.Negation_Operator: + operand = GetExpressionFromNode(nodes.Get_Operand(node)) + return InverseExpression(operand) + elif kind == nodes.Iir_Kind.Addition_Operator: + left = GetExpressionFromNode(nodes.Get_Left(node)) + right = GetExpressionFromNode(nodes.Get_Right(node)) + return AdditionExpression(left, right) + elif kind == nodes.Iir_Kind.Substraction_Operator: + left = GetExpressionFromNode(nodes.Get_Left(node)) + right = GetExpressionFromNode(nodes.Get_Right(node)) + return SubtractionExpression(left, right) + elif kind == nodes.Iir_Kind.Multiplication_Operator: + left = GetExpressionFromNode(nodes.Get_Left(node)) + right = GetExpressionFromNode(nodes.Get_Right(node)) + return MultiplyExpression(left, right) + elif kind == nodes.Iir_Kind.Division_Operator: + left = GetExpressionFromNode(nodes.Get_Left(node)) + right = GetExpressionFromNode(nodes.Get_Right(node)) + return DivisionExpression(left, right) + elif kind == nodes.Iir_Kind.Exponentiation_Operator: + left = GetExpressionFromNode(nodes.Get_Left(node)) + right = GetExpressionFromNode(nodes.Get_Right(node)) + return ExponentiationExpression(left, right) + else: + raise DOMException( + "Unknown expression kind '{kindName}'({kind}) in expression '{expr}'.".format( + kind=kind, kindName=kind.name, expr=node) + ) + +# FIXME: rewrite to generator +@export +def GetGenericsFromChainedNodes(nodeChain): + result = [] + for generic in utils.chain_iter(nodeChain): + kind = GetIirKindOfNode(generic) + if kind == nodes.Iir_Kind.Interface_Constant_Declaration: + from pyGHDL.dom.InterfaceItem import GenericConstantInterfaceItem + + genericConstant = GenericConstantInterfaceItem.parse(generic) + + result.append(genericConstant) + else: + raise DOMException( + "Unknown generic kind '{kindName}'({kind}) in generic '{generic}'.".format( + kind=kind, kindName=kind.name, generic=generic) + ) + + return result + +# FIXME: rewrite to generator +@export +def GetPortsFromChainedNodes(nodeChain): + result = [] + for port in utils.chain_iter(nodeChain): + kind = GetIirKindOfNode(port) + if kind == nodes.Iir_Kind.Interface_Signal_Declaration: + from pyGHDL.dom.InterfaceItem import PortSignalInterfaceItem + + portSignal = PortSignalInterfaceItem.parse(port) + + result.append(portSignal) + else: + raise DOMException( + "Unknown port kind '{kindName}'({kind}) in port '{port}'.".format( + kind=kind, kindName=kind.name, port=port) + ) + + return result + +def GetDeclaredItemsFromChainedNodes(nodeChain, entity: str, name: str): + result = [] + for item in utils.chain_iter(nodeChain): + kind = GetIirKindOfNode(item) + if kind == nodes.Iir_Kind.Constant_Declaration: + from pyGHDL.dom.Object import Constant + + constantName = NodeToName(item) + subTypeIndication = GetSubtypeIndicationFromNode(item, "constant", constantName) + defaultExpression = GetExpressionFromNode(nodes.Get_Default_Value(item)) + + constant = Constant(constantName, subTypeIndication, defaultExpression) + + result.append(constant) + elif kind == nodes.Iir_Kind.Signal_Declaration: + from pyGHDL.dom.Object import Signal + + signalName = NodeToName(item) + subTypeIndication = GetSubtypeIndicationFromNode(item, "signal", signalName) + defaultExpression = GetExpressionFromNode(nodes.Get_Default_Value(item)) + + constant = Signal(signalName, subTypeIndication, defaultExpression) + + result.append(constant) + elif kind == nodes.Iir_Kind.Anonymous_Type_Declaration: + typeName = NodeToName(item) + print("found type '{name}'".format(name=typeName)) + elif kind == nodes.Iir_Kind.Subtype_Declaration: + subTypeName = NodeToName(item) + print("found subtype '{name}'".format(name=subTypeName)) + elif kind == nodes.Iir_Kind.Function_Declaration: + functionName = NodeToName(item) + print("found function '{name}'".format(name=functionName)) + elif kind == nodes.Iir_Kind.Function_Body: + # functionName = NodeToName(item) + print("found function body '{name}'".format(name="????")) + elif kind == nodes.Iir_Kind.Object_Alias_Declaration: + aliasName = NodeToName(item) + print("found alias '{name}'".format(name=aliasName)) + else: + raise DOMException( + "Unknown declared item kind '{kindName}'({kind}) in {entity} '{name}'.".format( + kind=kind, kindName=kind.name, entity=entity, name=name) + ) + + return result diff --git a/pyGHDL/dom/_Utils.py b/pyGHDL/dom/_Utils.py new file mode 100644 index 000000000..f0c838517 --- /dev/null +++ b/pyGHDL/dom/_Utils.py @@ -0,0 +1,38 @@ +from pydecor import export + +from pyVHDLModel.VHDLModel import Mode + +from pyGHDL.libghdl import LibGHDLException, name_table +from pyGHDL.libghdl.vhdl import nodes + + +__all__ = [] + +__MODE_TRANSLATION = { + nodes.Iir_Mode.In_Mode: Mode.In, + nodes.Iir_Mode.Out_Mode: Mode.Out, + nodes.Iir_Mode.Inout_Mode: Mode.InOut, + nodes.Iir_Mode.Buffer_Mode: Mode.Buffer, + nodes.Iir_Mode.Linkage_Mode: Mode.Linkage +} + +@export +def GetIirKindOfNode(node) -> nodes.Iir_Kind: + kind: int = nodes.Get_Kind(node) + return nodes.Iir_Kind(kind) + + +@export +def NodeToName(node) -> str: + """Return the python string from node :obj:`node` identifier""" + identifier = nodes.Get_Identifier(node) + return name_table.Get_Name_Ptr(identifier) + + +@export +def GetModeOfNode(node) -> Mode: + """Return the mode of a :obj:`port`.""" + try: + return __MODE_TRANSLATION[nodes.Get_Mode(node)] + except KeyError: + raise LibGHDLException("Unknown mode.") diff --git a/pyGHDL/dom/__init__.py b/pyGHDL/dom/__init__.py index b57c20c28..b4ffaf4c6 100644 --- a/pyGHDL/dom/__init__.py +++ b/pyGHDL/dom/__init__.py @@ -1,19 +1,19 @@ # ============================================================================= -# ____ _ _ ____ _ _ -# _ __ _ _ / ___| | | | _ \| | __| | ___ _ __ ___ -# | '_ \| | | | | _| |_| | | | | | / _` |/ _ \| '_ ` _ \ -# | |_) | |_| | |_| | _ | |_| | |___ | (_| | (_) | | | | | | -# | .__/ \__, |\____|_| |_|____/|_____(_)__,_|\___/|_| |_| |_| -# |_| |___/ +# ____ _ _ ____ _ _ +# _ __ _ _ / ___| | | | _ \| | __| | ___ _ __ ___ +# | '_ \| | | | | _| |_| | | | | | / _` |/ _ \| '_ ` _ \ +# | |_) | |_| | |_| | _ | |_| | |___ | (_| | (_) | | | | | | +# | .__/ \__, |\____|_| |_|____/|_____(_)__,_|\___/|_| |_| |_| +# |_| |___/ # ============================================================================= -# Authors: -# Patrick Lehmann +# Authors: +# Patrick Lehmann # # Package package: Document object model (DOM) for pyGHDL.libghdl. # # License: # ============================================================================ -# Copyright (C) 2019-2020 Tristan Gingold +# 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 @@ -31,6 +31,4 @@ # SPDX-License-Identifier: GPL-2.0-or-later # ============================================================================ -from pydecor import export - __all__ = [] diff --git a/pyGHDL/dom/formatting/__init__.py b/pyGHDL/dom/formatting/__init__.py new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/pyGHDL/dom/formatting/__init__.py diff --git a/pyGHDL/dom/formatting/prettyprint.py b/pyGHDL/dom/formatting/prettyprint.py new file mode 100644 index 000000000..a64f2a4f5 --- /dev/null +++ b/pyGHDL/dom/formatting/prettyprint.py @@ -0,0 +1,296 @@ +from typing import List, Union + +from pydecor import export + +from pyGHDL.dom.Object import Constant, Signal +from pyVHDLModel.VHDLModel import GenericInterfaceItem, Expression, Direction, Mode, NamedEntity, PortInterfaceItem, BinaryExpression, IdentityExpression, \ + UnaryExpression + +from pyGHDL import GHDLBaseException +from pyGHDL.dom.Misc import Document +from pyGHDL.dom.DesignUnit import Entity, Architecture, Package, PackageBody, Configuration, Context +from pyGHDL.dom.InterfaceItem import GenericConstantInterfaceItem, PortSignalInterfaceItem +from pyGHDL.dom.Symbol import SimpleSubTypeSymbol, ConstrainedSubTypeSymbol, SimpleObjectSymbol +from pyGHDL.dom.Literal import IntegerLiteral, CharacterLiteral, FloatingPointLiteral + +from pyGHDL.dom.Expression import SubtractionExpression, AdditionExpression, MultiplyExpression, DivisionExpression, InverseExpression, AbsoluteExpression, \ + NegationExpression, ExponentiationExpression + +StringBuffer = List[str] + +DirectionTranslation = { + Direction.To: "to", + Direction.DownTo: "downto" +} + +ModeTranslation = { + Mode.In: "in", + Mode.Out: "out", + Mode.InOut: "inout", + Mode.Buffer: "buffer", + Mode.Linkage: "linkage" +} + +UnaryExpressionTranslation = { + IdentityExpression: " +", + NegationExpression: " -", + InverseExpression: "not ", + AbsoluteExpression: "abs ", +} + +BinaryExpressionTranslation = { + AdditionExpression: " + ", + SubtractionExpression: " - ", + MultiplyExpression: " * ", + DivisionExpression: " / ", + ExponentiationExpression: "**" +} + +@export +class PrettyPrintException(GHDLBaseException): + pass + +@export +class PrettyPrint: + # _buffer: StringBuffer + # + # def __init__(self): + # self._buffer = [] + + def formatDocument(self, document: Document, level: int = 0) -> StringBuffer: + buffer = [] + prefix = " " * level + buffer.append("{prefix}Document '{doc!s}':".format(doc=document.Path, prefix=prefix)) + buffer.append("{prefix} Entities:".format(prefix=prefix)) + for entity in document.Entities: + for line in self.formatEntity(entity, level+1): + buffer.append(line) + buffer.append("{prefix} Architectures:".format(prefix=prefix)) + for architecture in document.Architectures: + for line in self.formatArchitecture(architecture, level+1): + buffer.append(line) + buffer.append("{prefix} Packages:".format(prefix=prefix)) + for package in document.Packages: + for line in self.formatPackage(package, level+1): + buffer.append(line) + buffer.append("{prefix} PackageBodies:".format(prefix=prefix)) + for packageBodies in document.PackageBodies: + for line in self.formatPackageBody(packageBodies, level+1): + buffer.append(line) + buffer.append("{prefix} Configurations:".format(prefix=prefix)) + for configuration in document.Configurations: + for line in self.formatConfiguration(configuration, level+1): + buffer.append(line) + buffer.append("{prefix} Contexts:".format(prefix=prefix)) + for context in document.Contexts: + for line in self.formatContext(context, level+1): + buffer.append(line) + + return buffer + + def formatEntity(self, entity: Entity, level: int = 0) -> StringBuffer: + buffer = [] + prefix = " " * level + buffer.append("{prefix}- {name}".format(name=entity.Name, prefix=prefix)) + buffer.append("{prefix} Generics:".format(prefix=prefix)) + for generic in entity.GenericItems: + for line in self.formatGeneric(generic, level + 1): + buffer.append(line) + buffer.append("{prefix} Ports:".format(prefix=prefix)) + for port in entity.PortItems: + for line in self.formatPort(port, level + 1): + buffer.append(line) + buffer.append("{prefix} Declared:".format(prefix=prefix)) + for item in entity.DeclaredItems: + for line in self.formatDeclaredItems(item, level + 1): + buffer.append(line) + + return buffer + + def formatArchitecture(self, architecture: Architecture, level: int = 0) -> StringBuffer: + buffer = [] + prefix = " " * level + buffer.append("{prefix}- {name}".format(name=architecture.Name, prefix=prefix)) + buffer.append("{prefix} Declared:".format(prefix=prefix)) + for item in architecture.DeclaredItems: + for line in self.formatDeclaredItems(item, level + 2): + buffer.append(line) + + return buffer + + def formatPackage(self, package: Package, level: int = 0) -> StringBuffer: + buffer = [] + prefix = " " * level + buffer.append("{prefix}- {name}".format(name=package.Name, prefix=prefix)) + buffer.append("{prefix} Declared:".format(prefix=prefix)) + for item in package.DeclaredItems: + for line in self.formatDeclaredItems(item, level + 1): + buffer.append(line) + + return buffer + + def formatPackageBody(self, packageBody: PackageBody, level: int = 0) -> StringBuffer: + buffer = [] + prefix = " " * level + buffer.append("{prefix}- {name}".format(name=packageBody.Name, prefix=prefix)) + buffer.append("{prefix} Declared:".format(prefix=prefix)) + for item in packageBody.DeclaredItems: + for line in self.formatDeclaredItems(item, level + 1): + buffer.append(line) + + return buffer + + def formatConfiguration(self, configuration: Configuration, level: int = 0) -> StringBuffer: + buffer = [] + prefix = " " * level + buffer.append("{prefix}- {name}".format(name=configuration.Name, prefix=prefix)) + + return buffer + + def formatContext(self, context: Context, level: int = 0) -> StringBuffer: + buffer = [] + prefix = " " * level + buffer.append("{prefix}- {name}".format(name=context.Name, prefix=prefix)) + + return buffer + + def formatGeneric(self, generic: Union[NamedEntity, GenericInterfaceItem], level: int = 0) -> StringBuffer: + if isinstance(generic, GenericConstantInterfaceItem): + return self.formatGenericConstant(generic, level) + else: + raise PrettyPrintException("Unhandled generic kind for generic '{name}'.".format(name=generic.Name)) + + def formatPort(self, port: Union[NamedEntity, PortInterfaceItem], level: int = 0) -> StringBuffer: + if isinstance(port, PortSignalInterfaceItem): + return self.formatPortSignal(port, level) + else: + raise PrettyPrintException("Unhandled port kind for port '{name}'.".format(name=port.Name)) + + def formatGenericConstant(self, generic: GenericConstantInterfaceItem, level: int = 0) -> StringBuffer: + buffer = [] + prefix = " " * level + subType = generic.SubType + if isinstance(subType, SimpleSubTypeSymbol): + buffer.append( + "{prefix} - {name} : {mode} {type}".format( + prefix=prefix, + name=generic.Name, + mode=ModeTranslation[generic.Mode], + type=subType.SymbolName + ) + ) + elif isinstance(subType, ConstrainedSubTypeSymbol): + buffer.append( + "{prefix} - {name} : {mode} {type}({constraints})".format( + prefix=prefix, + name=generic.Name, + mode=ModeTranslation[generic.Mode], + type=subType.SymbolName, + constraints=", ".join( + ["{left} {dir} {right}".format( + left=self.formatExpression(constraint.Range.LeftBound), + right=self.formatExpression(constraint.Range.RightBound), + dir=DirectionTranslation[constraint.Range.Direction]) + for constraint in subType.Constraints]) + ) + ) + else: + raise PrettyPrintException("Unhandled constraint kind for generic '{name}'.".format(name=generic.Name)) + + return buffer + + def formatPortSignal(self, port: PortSignalInterfaceItem, level: int = 0) -> StringBuffer: + buffer = [] + prefix = " " * level + + buffer.append( + "{prefix} - {name} : {mode} {subtypeindication}".format( + prefix=prefix, + name=port.Name, + mode=ModeTranslation[port.Mode], + subtypeindication=self.formatSubtypeIndication(port.SubType, "port", port.Name) + ) + ) + + return buffer + + def formatDeclaredItems(self, item, level: int = 0) -> StringBuffer: + buffer = [] + prefix = " " * level + + if isinstance(item, Constant): + buffer.append( + "{prefix}- constant {name} : {subtype} := {expr}".format( + prefix=prefix, + name=item.Name, + subtype=self.formatSubtypeIndication(item.SubType, "constant", item.Name), + expr=self.formatExpression(item.DefaultExpression) + ) + ) + elif isinstance(item, Signal): + buffer.append( + "{prefix}- signal {name} : {subtype}{initValue}".format( + prefix=prefix, + name=item.Name, + subtype=self.formatSubtypeIndication(item.SubType, "signal", item.Name), + initValue=" := {expr}".format( + expr=self.formatExpression(item.DefaultExpression) + ) if item.DefaultExpression is not None else "" + ) + ) + else: + raise PrettyPrintException("Unhandled declared item kind.") + + return buffer + + def formatSubtypeIndication(self, subTypeIndication, entity: str, name: str) -> str: + if isinstance(subTypeIndication, SimpleSubTypeSymbol): + return "{type}".format(type=subTypeIndication.SymbolName) + elif isinstance(subTypeIndication, ConstrainedSubTypeSymbol): + constraints = ", ".join( + ["{left} {dir} {right}".format( + left=self.formatExpression(constraint.Range.LeftBound), + right=self.formatExpression(constraint.Range.RightBound), + dir=DirectionTranslation[constraint.Range.Direction] + ) for constraint in subTypeIndication.Constraints] + ) + + return "{type}({constraints})".format( + type=subTypeIndication.SymbolName, + constraints=constraints + ) + else: + raise PrettyPrintException("Unhandled constraint kind for {entity} '{name}'.".format(entity=entity, name=name)) + + def formatExpression(self, expression: Expression) -> str: + if isinstance(expression, SimpleObjectSymbol): + return "{name}".format(name=expression.SymbolName) + elif isinstance(expression, IntegerLiteral): + return "{value}".format(value=expression.Value) + elif isinstance(expression, FloatingPointLiteral): + return "{value}".format(value=expression.Value) + elif isinstance(expression, CharacterLiteral): + return "'{value}'".format(value=expression.Value) + elif isinstance(expression, UnaryExpression): + try: + operator = UnaryExpressionTranslation[type(expression)] + except KeyError: + raise PrettyPrintException("Unhandled operator for unary expression.") + + return "{operator}{operand}".format( + operand=self.formatExpression(expression.Operand), + operator=operator + ) + elif isinstance(expression, BinaryExpression): + try: + operator = BinaryExpressionTranslation[type(expression)] + except KeyError: + raise PrettyPrintException("Unhandled operator for binary expression.") + + return "{left}{operator}{right}".format( + left=self.formatExpression(expression.LeftOperand), + right=self.formatExpression(expression.RightOperand), + operator=operator + ) + else: + raise PrettyPrintException("Unhandled expression kind.") |