diff options
Diffstat (limited to 'pyGHDL')
-rwxr-xr-x | pyGHDL/cli/DOM.py | 34 | ||||
-rw-r--r-- | pyGHDL/dom/Aggregates.py | 38 | ||||
-rw-r--r-- | pyGHDL/dom/Attribute.py | 83 | ||||
-rw-r--r-- | pyGHDL/dom/Common.py | 53 | ||||
-rw-r--r-- | pyGHDL/dom/DesignUnit.py | 176 | ||||
-rw-r--r-- | pyGHDL/dom/Expression.py | 303 | ||||
-rw-r--r-- | pyGHDL/dom/InterfaceItem.py | 176 | ||||
-rw-r--r-- | pyGHDL/dom/Literal.py | 99 | ||||
-rw-r--r-- | pyGHDL/dom/Misc.py | 36 | ||||
-rw-r--r-- | pyGHDL/dom/Names.py | 99 | ||||
-rw-r--r-- | pyGHDL/dom/NonStandard.py | 79 | ||||
-rw-r--r-- | pyGHDL/dom/Object.py | 141 | ||||
-rw-r--r-- | pyGHDL/dom/Range.py | 8 | ||||
-rw-r--r-- | pyGHDL/dom/Subprogram.py | 41 | ||||
-rw-r--r-- | pyGHDL/dom/Symbol.py | 84 | ||||
-rw-r--r-- | pyGHDL/dom/Type.py | 178 | ||||
-rw-r--r-- | pyGHDL/dom/_Translate.py | 209 | ||||
-rw-r--r-- | pyGHDL/dom/_Utils.py | 50 | ||||
-rw-r--r-- | pyGHDL/dom/__init__.py | 73 | ||||
-rw-r--r-- | pyGHDL/dom/formatting/prettyprint.py | 78 | ||||
-rw-r--r-- | pyGHDL/libghdl/__init__.py | 10 | ||||
-rw-r--r-- | pyGHDL/libghdl/_decorator.py | 26 | ||||
-rw-r--r-- | pyGHDL/libghdl/files_map_editor.py | 4 | ||||
-rw-r--r-- | pyGHDL/requirements.txt | 2 |
24 files changed, 1540 insertions, 540 deletions
diff --git a/pyGHDL/cli/DOM.py b/pyGHDL/cli/DOM.py index dceafc629..622a70d16 100755 --- a/pyGHDL/cli/DOM.py +++ b/pyGHDL/cli/DOM.py @@ -4,12 +4,13 @@ from sys import argv from sys import exit as sysexit from pathlib import Path +from textwrap import dedent from pydecor import export from pyGHDL import GHDLBaseException from pyGHDL.libghdl import LibGHDLException -from pyGHDL.dom.Common import DOMException +from pyGHDL.dom import DOMException from pyGHDL.dom.NonStandard import Design, Document from pyGHDL.dom.formatting.prettyprint import PrettyPrint, PrettyPrintException @@ -41,6 +42,19 @@ class Application: print("\n".join(buffer)) + document: Document = self._design.Documents[0] + print() + print( + "libghdl processing time: {: 5.3f} us".format( + document.LibGHDLProcessingTime * 10 ** 6 + ) + ) + print( + "DOM translation time: {:5.3f} us".format( + document.DOMTranslationTime * 10 ** 6 + ) + ) + def handleException(ex): if isinstance(ex, PrettyPrintException): @@ -52,6 +66,7 @@ def handleException(ex): if ex2 is not None: for message in ex2.InternalErrors: print("libghdl: {message}".format(message=message)) + return 0 return 4 elif isinstance(ex, LibGHDLException): print("LIB:", ex) @@ -81,8 +96,23 @@ def main(items=argv[1:]): app = Application() app.addFile(Path(item), "default_lib") app.prettyPrint() - except Exception as ex: + except GHDLBaseException as ex: _exitcode = handleException(ex) + except Exception as ex: + print( + dedent( + """\ + Fatal: An unhandled exception has reached to the top-most exception handler. + Exception: {name} + """.format( + name=ex.__class__.__name__ + ) + ) + ) + if isinstance(ex, ValueError): + print(" Message: {msg}".format(msg=str(ex))) + if ex.__cause__ is not None: + print("Cause: {msg}".format(msg=str(ex.__cause__))) return _exitcode diff --git a/pyGHDL/dom/Aggregates.py b/pyGHDL/dom/Aggregates.py index ac8ecbca8..32dc1cacf 100644 --- a/pyGHDL/dom/Aggregates.py +++ b/pyGHDL/dom/Aggregates.py @@ -41,8 +41,6 @@ This module contains all DOM classes for VHDL's design units (:class:`context <E """ from pydecor import export -from pyGHDL.dom.Range import Range -from pyGHDL.dom.Symbol import EnumerationLiteralSymbol from pyVHDLModel.VHDLModel import ( SimpleAggregateElement as VHDLModel_SimpleAggregateElement, IndexedAggregateElement as VHDLModel_IndexedAggregateElement, @@ -51,44 +49,60 @@ from pyVHDLModel.VHDLModel import ( OthersAggregateElement as VHDLModel_OthersAggregateElement, Expression, ) +from pyGHDL.libghdl._types import Iir +from pyGHDL.dom import DOMMixin +from pyGHDL.dom.Range import Range +from pyGHDL.dom.Symbol import EnumerationLiteralSymbol __all__ = [] @export -class SimpleAggregateElement(VHDLModel_SimpleAggregateElement): - def __init__(self, expression: Expression): +class SimpleAggregateElement(VHDLModel_SimpleAggregateElement, DOMMixin): + def __init__(self, node: Iir, expression: Expression): super().__init__() + DOMMixin.__init__(self, node) + self._expression = expression @export -class IndexedAggregateElement(VHDLModel_IndexedAggregateElement): - def __init__(self, index: Expression, expression: Expression): +class IndexedAggregateElement(VHDLModel_IndexedAggregateElement, DOMMixin): + def __init__(self, node: Iir, index: Expression, expression: Expression): super().__init__() + DOMMixin.__init__(self, node) + self._index = index self._expression = expression @export -class RangedAggregateElement(VHDLModel_RangedAggregateElement): - def __init__(self, r: Range, expression: Expression): +class RangedAggregateElement(VHDLModel_RangedAggregateElement, DOMMixin): + def __init__(self, node: Iir, r: Range, expression: Expression): super().__init__() + DOMMixin.__init__(self, node) + self._range = r self._expression = expression @export -class NamedAggregateElement(VHDLModel_NamedAggregateElement): - def __init__(self, name: EnumerationLiteralSymbol, expression: Expression): +class NamedAggregateElement(VHDLModel_NamedAggregateElement, DOMMixin): + def __init__( + self, node: Iir, name: EnumerationLiteralSymbol, expression: Expression + ): super().__init__() + DOMMixin.__init__(self, node) + self._name = name self._expression = expression @export -class OthersAggregateElement(VHDLModel_OthersAggregateElement): - def __init__(self, expression: Expression): +class OthersAggregateElement(VHDLModel_OthersAggregateElement, DOMMixin): + def __init__(self, node: Iir, expression: Expression): super().__init__() + DOMMixin.__init__(self, node) + self._expression = expression diff --git a/pyGHDL/dom/Attribute.py b/pyGHDL/dom/Attribute.py new file mode 100644 index 000000000..8c7b08190 --- /dev/null +++ b/pyGHDL/dom/Attribute.py @@ -0,0 +1,83 @@ +# ============================================================================= +# ____ _ _ ____ _ _ +# _ __ _ _ / ___| | | | _ \| | __| | ___ _ __ ___ +# | '_ \| | | | | _| |_| | | | | | / _` |/ _ \| '_ ` _ \ +# | |_) | |_| | |_| | _ | |_| | |___ | (_| | (_) | | | | | | +# | .__/ \__, |\____|_| |_|____/|_____(_)__,_|\___/|_| |_| |_| +# |_| |___/ +# ============================================================================= +# 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 ( + Attribute as VHDLModel_Attribute, + AttributeSpecification as VHDLModel_AttributeSpecification, + Name, + SubTypeOrSymbol, +) +from pyGHDL.libghdl._types import Iir +from pyGHDL.libghdl.vhdl import nodes +from pyGHDL.dom import DOMMixin +from pyGHDL.dom._Utils import GetNameOfNode, GetIirKindOfNode +from pyGHDL.dom._Translate import GetNameFromNode +from pyGHDL.dom.Symbol import SimpleSubTypeSymbol + + +@export +class Attribute(VHDLModel_Attribute, DOMMixin): + def __init__(self, node: Iir, name: str, subType: SubTypeOrSymbol): + super().__init__(name, subType) + DOMMixin.__init__(self, node) + + @classmethod + def parse(cls, attributeNode: Iir) -> "Attribute": + name = GetNameOfNode(attributeNode) + subTypeMark = nodes.Get_Type_Mark(attributeNode) + subTypeName = GetNameOfNode(subTypeMark) + + subType = SimpleSubTypeSymbol(subTypeMark, subTypeName) + return cls(attributeNode, name, subType) + + +@export +class AttributeSpecification(VHDLModel_AttributeSpecification, DOMMixin): + def __init__(self, node: Iir, attribute: Name): + super().__init__(attribute) + DOMMixin.__init__(self, node) + + @classmethod + def parse(cls, attributeNode: Iir) -> "AttributeSpecification": + attributeDesignator = nodes.Get_Attribute_Designator(attributeNode) + attributeName = GetNameFromNode(attributeDesignator) + + # FIXME: needs an implementation + entityNameList = nodes.Get_Entity_Name_List(attributeNode) + enlk = GetIirKindOfNode(entityNameList) + + entityClass = nodes.Get_Entity_Class(attributeNode) + eck = GetIirKindOfNode(entityClass) + + return cls(attributeNode, attributeName) diff --git a/pyGHDL/dom/Common.py b/pyGHDL/dom/Common.py deleted file mode 100644 index 43e8ce497..000000000 --- a/pyGHDL/dom/Common.py +++ /dev/null @@ -1,53 +0,0 @@ -# ============================================================================= -# ____ _ _ ____ _ _ -# _ __ _ _ / ___| | | | _ \| | __| | ___ _ __ ___ -# | '_ \| | | | | _| |_| | | | | | / _` |/ _ \| '_ ` _ \ -# | |_) | |_| | |_| | _ | |_| | |___ | (_| | (_) | | | | | | -# | .__/ \__, |\____|_| |_|____/|_____(_)__,_|\___/|_| |_| |_| -# |_| |___/ -# ============================================================================= -# Authors: -# Patrick Lehmann -# -# Package module: DOM: Common classes for package pyGHDL.dom. -# -# 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 -# ============================================================================ - -""" -.. todo:: - Add a module documentation. -""" -from pydecor import export - -from pyGHDL import GHDLBaseException -from pyGHDL.libghdl import LibGHDLException, errorout_memory - -__all__ = [] - - -@export -class DOMException(GHDLBaseException): - pass - - -@export -class GHDLException(GHDLBaseException): - pass diff --git a/pyGHDL/dom/DesignUnit.py b/pyGHDL/dom/DesignUnit.py index bf16b5c4b..a8249d38d 100644 --- a/pyGHDL/dom/DesignUnit.py +++ b/pyGHDL/dom/DesignUnit.py @@ -39,18 +39,26 @@ This module contains all DOM classes for VHDL's design units (:class:`context <E """ +from typing import List + +from pyGHDL.dom import DOMMixin from pyGHDL.libghdl._types import Iir from pydecor import export from pyVHDLModel.VHDLModel import ( + UseClause as VHDLModel_UseClause, Entity as VHDLModel_Entity, - EntityOrSymbol, Architecture as VHDLModel_Architecture, Package as VHDLModel_Package, PackageBody as VHDLModel_PackageBody, + PackageInstantiation as VHDLModel_PackageInstantiation, Context as VHDLModel_Context, Configuration as VHDLModel_Configuration, Component as VHDLModel_Component, + GenericInterfaceItem, + PortInterfaceItem, + EntityOrSymbol, + Name, ) from pyGHDL.libghdl.vhdl import nodes @@ -67,7 +75,35 @@ __all__ = [] @export -class Entity(VHDLModel_Entity): +class UseClause(VHDLModel_UseClause, DOMMixin): + def __init__(self, node: Iir, name: str): + super().__init__(name) + DOMMixin.__init__(self, node) + + @classmethod + def parse(cls, useNode: Iir): + from pyGHDL.dom._Translate import GetNameFromNode + + selectedName = nodes.Get_Selected_Name(useNode) + name = GetNameFromNode(selectedName) + + return cls(useNode, name) + + +@export +class Entity(VHDLModel_Entity, DOMMixin): + def __init__( + self, + node: Iir, + name: str, + genericItems: List[GenericInterfaceItem] = None, + portItems: List[PortInterfaceItem] = None, + declaredItems: List = None, + bodyItems: List["ConcurrentStatement"] = None, + ): + super().__init__(name, genericItems, portItems, declaredItems, bodyItems) + DOMMixin.__init__(self, node) + @classmethod def parse(cls, entityNode: Iir): name = GetNameOfNode(entityNode) @@ -78,55 +114,102 @@ class Entity(VHDLModel_Entity): ) bodyItems = [] - return cls(name, generics, ports, declaredItems, bodyItems) + return cls(entityNode, name, generics, ports, declaredItems, bodyItems) @export -class Architecture(VHDLModel_Architecture): +class Architecture(VHDLModel_Architecture, DOMMixin): + def __init__( + self, + node: Iir, + name: str, + entity: EntityOrSymbol, + declaredItems: List = None, + bodyItems: List["ConcurrentStatement"] = None, + ): + super().__init__(name, entity, declaredItems, bodyItems) + DOMMixin.__init__(self, node) + @classmethod def parse(cls, architectureNode: Iir): name = GetNameOfNode(architectureNode) - entityName = GetNameOfNode(nodes.Get_Entity_Name(architectureNode)) - entity = EntitySymbol(entityName) + entityNameNode = nodes.Get_Entity_Name(architectureNode) + entityName = GetNameOfNode(entityNameNode) + entity = EntitySymbol(entityNameNode, entityName) declaredItems = GetDeclaredItemsFromChainedNodes( nodes.Get_Declaration_Chain(architectureNode), "architecture", name ) bodyItems = [] - return cls(name, entity, declaredItems, bodyItems) + return cls(architectureNode, name, entity, declaredItems, bodyItems) def resolve(self): pass @export -class Component(VHDLModel_Component): +class Component(VHDLModel_Component, DOMMixin): + def __init__( + self, + node: Iir, + name: str, + genericItems: List[GenericInterfaceItem] = None, + portItems: List[PortInterfaceItem] = None, + ): + super().__init__(name, genericItems, portItems) + DOMMixin.__init__(self, node) + @classmethod def parse(cls, componentNode: Iir): name = GetNameOfNode(componentNode) generics = GetGenericsFromChainedNodes(nodes.Get_Generic_Chain(componentNode)) ports = GetPortsFromChainedNodes(nodes.Get_Port_Chain(componentNode)) - return cls(name, generics, ports) + return cls(componentNode, name, generics, ports) @export -class Package(VHDLModel_Package): +class Package(VHDLModel_Package, DOMMixin): + def __init__( + self, + node: Iir, + name: str, + genericItems: List[GenericInterfaceItem] = None, + declaredItems: List = None, + ): + super().__init__(name, genericItems, declaredItems) + DOMMixin.__init__(self, node) + @classmethod def parse(cls, packageNode: Iir): name = GetNameOfNode(packageNode) - generics = ( - None # GetGenericsFromChainedNodes(nodes.Get_Generic_Chain(packageNode)) - ) + + packageHeader = nodes.Get_Package_Header(packageNode) + if packageHeader is not nodes.Null_Iir: + generics = GetGenericsFromChainedNodes( + nodes.Get_Generic_Chain(packageHeader) + ) + else: + generics = [] + declaredItems = GetDeclaredItemsFromChainedNodes( nodes.Get_Declaration_Chain(packageNode), "package", name ) - return cls(name, generics, declaredItems) + return cls(packageNode, name, generics, declaredItems) @export -class PackageBody(VHDLModel_PackageBody): +class PackageBody(VHDLModel_PackageBody, DOMMixin): + def __init__( + self, + node: Iir, + name: str, + declaredItems: List = None, + ): + super().__init__(name, declaredItems) + DOMMixin.__init__(self, node) + @classmethod def parse(cls, packageBodyNode: Iir): name = GetNameOfNode(packageBodyNode) @@ -134,20 +217,65 @@ class PackageBody(VHDLModel_PackageBody): nodes.Get_Declaration_Chain(packageBodyNode), "package", name ) - return cls(name, declaredItems) + return cls(packageBodyNode, name, declaredItems) + + +@export +class PackageInstantiation(VHDLModel_PackageInstantiation, DOMMixin): + def __init__( + self, + node: Iir, + name: str, + uninstantiatedPackageName: Name, + # genericItems: List[GenericInterfaceItem] = None, + ): + super().__init__(name, uninstantiatedPackageName) + DOMMixin.__init__(self, node) + + @classmethod + def parse(cls, packageNode: Iir): + name = GetNameOfNode(packageNode) + uninstantiatedPackageName = nodes.Get_Uninstantiated_Package_Name(packageNode) + + # FIXME: read generics + # FIXME: read generic map + + return cls(packageNode, name, uninstantiatedPackageName) @export -class Context(VHDLModel_Context): +class Context(VHDLModel_Context, DOMMixin): + def __init__( + self, + node: Iir, + name: str, + ): + super().__init__(name) + DOMMixin.__init__(self, node) + @classmethod - def parse(cls, libraryUnit: Iir): - name = GetNameOfNode(libraryUnit) - return cls(name) + def parse(cls, contextNode: Iir): + name = GetNameOfNode(contextNode) + + # FIXME: read use clauses + + return cls(contextNode, name) @export -class Configuration(VHDLModel_Configuration): +class Configuration(VHDLModel_Configuration, DOMMixin): + def __init__( + self, + node: Iir, + name: str, + ): + super().__init__(name) + DOMMixin.__init__(self, node) + @classmethod - def parse(cls, configuration: Iir): - name = GetNameOfNode(configuration) - return cls(name) + def parse(cls, configurationNode: Iir): + name = GetNameOfNode(configurationNode) + + # FIXME: needs an implementation + + return cls(configurationNode, name) diff --git a/pyGHDL/dom/Expression.py b/pyGHDL/dom/Expression.py index b129e1ce5..b3256d551 100644 --- a/pyGHDL/dom/Expression.py +++ b/pyGHDL/dom/Expression.py @@ -34,6 +34,7 @@ from typing import List from pydecor import export +from pyGHDL.dom import DOMMixin, DOMException from pyVHDLModel.VHDLModel import ( InverseExpression as VHDLModel_InverseExpression, IdentityExpression as VHDLModel_IdentityExpression, @@ -43,6 +44,9 @@ from pyVHDLModel.VHDLModel import ( TypeConversion as VHDLModel_TypeConversion, FunctionCall as VHDLModel_FunctionCall, QualifiedExpression as VHDLModel_QualifiedExpression, + RangeExpression as VHDLModel_RangeExpression, + AscendingRangeExpression as VHDLModel_AscendingRangeExpression, + DescendingRangeExpression as VHDLModel_DescendingRangeExpression, AdditionExpression as VHDLModel_AdditionExpression, SubtractionExpression as VHDLModel_SubtractionExpression, ConcatenationExpression as VHDLModel_ConcatenationExpression, @@ -76,9 +80,9 @@ from pyVHDLModel.VHDLModel import ( ) from pyGHDL.libghdl import utils +from pyGHDL.libghdl._types import Iir from pyGHDL.libghdl.vhdl import nodes from pyGHDL.dom._Utils import GetIirKindOfNode -from pyGHDL.dom.Common import DOMException from pyGHDL.dom.Symbol import EnumerationLiteralSymbol, SimpleSubTypeSymbol from pyGHDL.dom.Aggregates import ( OthersAggregateElement, @@ -94,308 +98,435 @@ __all__ = [] class _ParseUnaryExpression: @classmethod - def parse(cls, node): + def parse(cls, node: Iir): from pyGHDL.dom._Translate import GetExpressionFromNode operand = GetExpressionFromNode(nodes.Get_Operand(node)) - return cls(operand) + return cls(node, operand) class _ParseBinaryExpression: @classmethod - def parse(cls, node): + def parse(cls, node: Iir): from pyGHDL.dom._Translate import GetExpressionFromNode left = GetExpressionFromNode(nodes.Get_Left(node)) right = GetExpressionFromNode(nodes.Get_Right(node)) - return cls(left, right) + return cls(node, left, right) @export -class InverseExpression(VHDLModel_InverseExpression, _ParseUnaryExpression): - def __init__(self, operand: Expression): +class InverseExpression(VHDLModel_InverseExpression, DOMMixin, _ParseUnaryExpression): + def __init__(self, node: Iir, operand: Expression): super().__init__() + DOMMixin.__init__(self, node) + self._operand = operand @export -class IdentityExpression(VHDLModel_IdentityExpression, _ParseUnaryExpression): - def __init__(self, operand: Expression): +class IdentityExpression(VHDLModel_IdentityExpression, DOMMixin, _ParseUnaryExpression): + def __init__(self, node: Iir, operand: Expression): super().__init__() + DOMMixin.__init__(self, node) + self._operand = operand @export -class NegationExpression(VHDLModel_NegationExpression, _ParseUnaryExpression): - def __init__(self, operand: Expression): +class NegationExpression(VHDLModel_NegationExpression, DOMMixin, _ParseUnaryExpression): + def __init__(self, node: Iir, operand: Expression): super().__init__() + DOMMixin.__init__(self, node) + self._operand = operand @export -class AbsoluteExpression(VHDLModel_AbsoluteExpression, _ParseUnaryExpression): - def __init__(self, operand: Expression): +class AbsoluteExpression(VHDLModel_AbsoluteExpression, DOMMixin, _ParseUnaryExpression): + def __init__(self, node: Iir, operand: Expression): super().__init__() + DOMMixin.__init__(self, node) + self._operand = operand @export -class ParenthesisExpression(VHDLModel_ParenthesisExpression, _ParseUnaryExpression): - def __init__(self, operand: Expression): +class ParenthesisExpression( + VHDLModel_ParenthesisExpression, DOMMixin, _ParseUnaryExpression +): + def __init__(self, node: Iir, operand: Expression): super().__init__() + DOMMixin.__init__(self, node) + self._operand = operand @classmethod - def parse(cls, node): + def parse(cls, node: Iir): from pyGHDL.dom._Translate import GetExpressionFromNode operand = GetExpressionFromNode(nodes.Get_Expression(node)) - return cls(operand) + return cls(node, operand) @export -class TypeConversion(VHDLModel_TypeConversion): - def __init__(self, operand: Expression): +class TypeConversion(VHDLModel_TypeConversion, DOMMixin): + def __init__(self, node: Iir, operand: Expression): super().__init__() + DOMMixin.__init__(self, node) + self._operand = operand @export -class FunctionCall(VHDLModel_FunctionCall): - def __init__(self, operand: Expression): +class FunctionCall(VHDLModel_FunctionCall, DOMMixin): + def __init__(self, node: Iir, operand: Expression): super().__init__() + DOMMixin.__init__(self, node) + self._operand = operand +class RangeExpression(VHDLModel_RangeExpression, DOMMixin): + @classmethod + def parse(cls, node: Iir) -> "VHDLModel_RangeExpression": + from pyGHDL.dom._Translate import GetExpressionFromNode + + direction = nodes.Get_Direction(node) + leftBound = GetExpressionFromNode(nodes.Get_Left_Limit_Expr(node)) + rightBound = GetExpressionFromNode(nodes.Get_Right_Limit_Expr(node)) + + if not direction: # ascending + return AscendingRangeExpression(node, leftBound, rightBound) + else: + return DescendingRangeExpression(node, leftBound, rightBound) + + +@export +class AscendingRangeExpression(VHDLModel_AscendingRangeExpression, DOMMixin): + def __init__(self, node: Iir, left: Expression, right: Expression): + super().__init__() + DOMMixin.__init__(self, node) + + self._leftOperand = left + self._rightOperand = right + + @export -class AdditionExpression(VHDLModel_AdditionExpression, _ParseBinaryExpression): - def __init__(self, left: Expression, right: Expression): +class DescendingRangeExpression(VHDLModel_DescendingRangeExpression, DOMMixin): + def __init__(self, node: Iir, left: Expression, right: Expression): super().__init__() + DOMMixin.__init__(self, node) + self._leftOperand = left self._rightOperand = right @export -class SubtractionExpression(VHDLModel_SubtractionExpression, _ParseBinaryExpression): - def __init__(self, left: Expression, right: Expression): +class AdditionExpression( + VHDLModel_AdditionExpression, DOMMixin, _ParseBinaryExpression +): + def __init__(self, node: Iir, left: Expression, right: Expression): super().__init__() + DOMMixin.__init__(self, node) + + self._leftOperand = left + self._rightOperand = right + + +@export +class SubtractionExpression( + VHDLModel_SubtractionExpression, DOMMixin, _ParseBinaryExpression +): + def __init__(self, node: Iir, left: Expression, right: Expression): + super().__init__() + DOMMixin.__init__(self, node) + self._leftOperand = left self._rightOperand = right @export class ConcatenationExpression( - VHDLModel_ConcatenationExpression, _ParseBinaryExpression + VHDLModel_ConcatenationExpression, DOMMixin, _ParseBinaryExpression ): - def __init__(self, left: Expression, right: Expression): + def __init__(self, node: Iir, left: Expression, right: Expression): super().__init__() + DOMMixin.__init__(self, node) + self._leftOperand = left self._rightOperand = right @export -class MultiplyExpression(VHDLModel_MultiplyExpression, _ParseBinaryExpression): - def __init__(self, left: Expression, right: Expression): +class MultiplyExpression( + VHDLModel_MultiplyExpression, DOMMixin, _ParseBinaryExpression +): + def __init__(self, node: Iir, left: Expression, right: Expression): super().__init__() + DOMMixin.__init__(self, node) + self._leftOperand = left self._rightOperand = right @export -class DivisionExpression(VHDLModel_DivisionExpression, _ParseBinaryExpression): - def __init__(self, left: Expression, right: Expression): +class DivisionExpression( + VHDLModel_DivisionExpression, DOMMixin, _ParseBinaryExpression +): + def __init__(self, node: Iir, left: Expression, right: Expression): super().__init__() + DOMMixin.__init__(self, node) + self._leftOperand = left self._rightOperand = right @export -class RemainderExpression(VHDLModel_RemainderExpression, _ParseBinaryExpression): - def __init__(self, left: Expression, right: Expression): +class RemainderExpression( + VHDLModel_RemainderExpression, DOMMixin, _ParseBinaryExpression +): + def __init__(self, node: Iir, left: Expression, right: Expression): super().__init__() + DOMMixin.__init__(self, node) + self._leftOperand = left self._rightOperand = right @export -class ModuloExpression(VHDLModel_ModuloExpression, _ParseBinaryExpression): - def __init__(self, left: Expression, right: Expression): +class ModuloExpression(VHDLModel_ModuloExpression, DOMMixin, _ParseBinaryExpression): + def __init__(self, node: Iir, left: Expression, right: Expression): super().__init__() + DOMMixin.__init__(self, node) + self._leftOperand = left self._rightOperand = right @export class ExponentiationExpression( - VHDLModel_ExponentiationExpression, _ParseBinaryExpression + VHDLModel_ExponentiationExpression, DOMMixin, _ParseBinaryExpression ): - def __init__(self, left: Expression, right: Expression): + def __init__(self, node: Iir, left: Expression, right: Expression): super().__init__() + DOMMixin.__init__(self, node) + self._leftOperand = left self._rightOperand = right @export -class AndExpression(VHDLModel_AndExpression, _ParseBinaryExpression): - def __init__(self, left: Expression, right: Expression): +class AndExpression(VHDLModel_AndExpression, DOMMixin, _ParseBinaryExpression): + def __init__(self, node: Iir, left: Expression, right: Expression): super().__init__() + DOMMixin.__init__(self, node) + self._leftOperand = left self._rightOperand = right @export -class NandExpression(VHDLModel_NandExpression, _ParseBinaryExpression): - def __init__(self, left: Expression, right: Expression): +class NandExpression(VHDLModel_NandExpression, DOMMixin, _ParseBinaryExpression): + def __init__(self, node: Iir, left: Expression, right: Expression): super().__init__() + DOMMixin.__init__(self, node) + self._leftOperand = left self._rightOperand = right @export -class OrExpression(VHDLModel_OrExpression, _ParseBinaryExpression): - def __init__(self, left: Expression, right: Expression): +class OrExpression(VHDLModel_OrExpression, DOMMixin, _ParseBinaryExpression): + def __init__(self, node: Iir, left: Expression, right: Expression): super().__init__() + DOMMixin.__init__(self, node) + self._leftOperand = left self._rightOperand = right @export -class NorExpression(VHDLModel_NorExpression, _ParseBinaryExpression): - def __init__(self, left: Expression, right: Expression): +class NorExpression(VHDLModel_NorExpression, DOMMixin, _ParseBinaryExpression): + def __init__(self, node: Iir, left: Expression, right: Expression): super().__init__() + DOMMixin.__init__(self, node) + self._leftOperand = left self._rightOperand = right @export -class XorExpression(VHDLModel_XorExpression, _ParseBinaryExpression): - def __init__(self, left: Expression, right: Expression): +class XorExpression(VHDLModel_XorExpression, DOMMixin, _ParseBinaryExpression): + def __init__(self, node: Iir, left: Expression, right: Expression): super().__init__() + DOMMixin.__init__(self, node) + self._leftOperand = left self._rightOperand = right @export -class XnorExpression(VHDLModel_XnorExpression, _ParseBinaryExpression): - def __init__(self, left: Expression, right: Expression): +class XnorExpression(VHDLModel_XnorExpression, DOMMixin, _ParseBinaryExpression): + def __init__(self, node: Iir, left: Expression, right: Expression): super().__init__() + DOMMixin.__init__(self, node) + self._leftOperand = left self._rightOperand = right @export -class EqualExpression(VHDLModel_EqualExpression, _ParseBinaryExpression): - def __init__(self, left: Expression, right: Expression): +class EqualExpression(VHDLModel_EqualExpression, DOMMixin, _ParseBinaryExpression): + def __init__(self, node: Iir, left: Expression, right: Expression): super().__init__() + DOMMixin.__init__(self, node) + self._leftOperand = left self._rightOperand = right @export -class UnequalExpression(VHDLModel_UnequalExpression, _ParseBinaryExpression): - def __init__(self, left: Expression, right: Expression): +class UnequalExpression(VHDLModel_UnequalExpression, DOMMixin, _ParseBinaryExpression): + def __init__(self, node: Iir, left: Expression, right: Expression): super().__init__() + DOMMixin.__init__(self, node) + self._leftOperand = left self._rightOperand = right @export -class LessThanExpression(VHDLModel_LessThanExpression, _ParseBinaryExpression): - def __init__(self, left: Expression, right: Expression): +class LessThanExpression( + VHDLModel_LessThanExpression, DOMMixin, _ParseBinaryExpression +): + def __init__(self, node: Iir, left: Expression, right: Expression): super().__init__() + DOMMixin.__init__(self, node) + self._leftOperand = left self._rightOperand = right @export -class LessEqualExpression(VHDLModel_LessEqualExpression, _ParseBinaryExpression): - def __init__(self, left: Expression, right: Expression): +class LessEqualExpression( + VHDLModel_LessEqualExpression, DOMMixin, _ParseBinaryExpression +): + def __init__(self, node: Iir, left: Expression, right: Expression): super().__init__() + DOMMixin.__init__(self, node) + self._leftOperand = left self._rightOperand = right @export -class GreaterThanExpression(VHDLModel_GreaterThanExpression, _ParseBinaryExpression): - def __init__(self, left: Expression, right: Expression): +class GreaterThanExpression( + VHDLModel_GreaterThanExpression, DOMMixin, _ParseBinaryExpression +): + def __init__(self, node: Iir, left: Expression, right: Expression): super().__init__() + DOMMixin.__init__(self, node) + self._leftOperand = left self._rightOperand = right @export -class GreaterEqualExpression(VHDLModel_GreaterEqualExpression, _ParseBinaryExpression): - def __init__(self, left: Expression, right: Expression): +class GreaterEqualExpression( + VHDLModel_GreaterEqualExpression, DOMMixin, _ParseBinaryExpression +): + def __init__(self, node: Iir, left: Expression, right: Expression): super().__init__() + DOMMixin.__init__(self, node) + self._leftOperand = left self._rightOperand = right @export class ShiftRightLogicExpression( - VHDLModel_ShiftRightLogicExpression, _ParseBinaryExpression + VHDLModel_ShiftRightLogicExpression, DOMMixin, _ParseBinaryExpression ): - def __init__(self, left: Expression, right: Expression): + def __init__(self, node: Iir, left: Expression, right: Expression): super().__init__() + DOMMixin.__init__(self, node) + self._leftOperand = left self._rightOperand = right @export class ShiftLeftLogicExpression( - VHDLModel_ShiftLeftLogicExpression, _ParseBinaryExpression + VHDLModel_ShiftLeftLogicExpression, DOMMixin, _ParseBinaryExpression ): - def __init__(self, left: Expression, right: Expression): + def __init__(self, node: Iir, left: Expression, right: Expression): super().__init__() + DOMMixin.__init__(self, node) + self._leftOperand = left self._rightOperand = right @export class ShiftRightArithmeticExpression( - VHDLModel_ShiftRightArithmeticExpression, _ParseBinaryExpression + VHDLModel_ShiftRightArithmeticExpression, DOMMixin, _ParseBinaryExpression ): - def __init__(self, left: Expression, right: Expression): + def __init__(self, node: Iir, left: Expression, right: Expression): super().__init__() + DOMMixin.__init__(self, node) + self._leftOperand = left self._rightOperand = right @export class ShiftLeftArithmeticExpression( - VHDLModel_ShiftLeftArithmeticExpression, _ParseBinaryExpression + VHDLModel_ShiftLeftArithmeticExpression, DOMMixin, _ParseBinaryExpression ): - def __init__(self, left: Expression, right: Expression): + def __init__(self, node: Iir, left: Expression, right: Expression): super().__init__() + DOMMixin.__init__(self, node) + self._leftOperand = left self._rightOperand = right @export -class RotateRightExpression(VHDLModel_RotateRightExpression, _ParseBinaryExpression): - def __init__(self, left: Expression, right: Expression): +class RotateRightExpression( + VHDLModel_RotateRightExpression, DOMMixin, _ParseBinaryExpression +): + def __init__(self, node: Iir, left: Expression, right: Expression): super().__init__() + DOMMixin.__init__(self, node) + self._leftOperand = left self._rightOperand = right @export -class RotateLeftExpression(VHDLModel_RotateLeftExpression, _ParseBinaryExpression): - def __init__(self, left: Expression, right: Expression): +class RotateLeftExpression( + VHDLModel_RotateLeftExpression, DOMMixin, _ParseBinaryExpression +): + def __init__(self, node: Iir, left: Expression, right: Expression): super().__init__() + DOMMixin.__init__(self, node) + self._leftOperand = left self._rightOperand = right @export -class QualifiedExpression(VHDLModel_QualifiedExpression): - def __init__(self, subType: SubTypeOrSymbol, operand: Expression): +class QualifiedExpression(VHDLModel_QualifiedExpression, DOMMixin): + def __init__(self, node: Iir, subType: SubTypeOrSymbol, operand: Expression): super().__init__() + DOMMixin.__init__(self, node) + self._subtype = subType self._operand = operand @classmethod - def parse(cls, node): + def parse(cls, node: Iir): from pyGHDL.dom._Translate import GetExpressionFromNode, GetNameOfNode typeMarkName = GetNameOfNode(nodes.Get_Type_Mark(node)) @@ -405,13 +536,15 @@ class QualifiedExpression(VHDLModel_QualifiedExpression): @export -class Aggregate(VHDLModel_Aggregate): - def __init__(self, elements: List[AggregateElement]): +class Aggregate(VHDLModel_Aggregate, DOMMixin): + def __init__(self, node: Iir, elements: List[AggregateElement]): super().__init__() + DOMMixin.__init__(self, node) + self._elements = elements @classmethod - def parse(cls, node): + def parse(cls, node: Iir): from pyGHDL.dom._Translate import GetExpressionFromNode, GetRangeFromNode choices = [] @@ -422,18 +555,18 @@ class Aggregate(VHDLModel_Aggregate): value = GetExpressionFromNode(nodes.Get_Associated_Expr(item)) if kind == nodes.Iir_Kind.Choice_By_None: - choices.append(SimpleAggregateElement(value)) + choices.append(SimpleAggregateElement(item, value)) elif kind == nodes.Iir_Kind.Choice_By_Expression: index = GetExpressionFromNode(nodes.Get_Choice_Expression(item)) - choices.append(IndexedAggregateElement(index, value)) + choices.append(IndexedAggregateElement(item, index, value)) elif kind == nodes.Iir_Kind.Choice_By_Range: r = GetRangeFromNode(nodes.Get_Choice_Range(item)) - choices.append(RangedAggregateElement(r, value)) + choices.append(RangedAggregateElement(item, r, value)) elif kind == nodes.Iir_Kind.Choice_By_Name: name = EnumerationLiteralSymbol(nodes.Get_Choice_Name(item)) - choices.append(NamedAggregateElement(name, value)) + choices.append(NamedAggregateElement(item, name, value)) elif kind == nodes.Iir_Kind.Choice_By_Others: - choices.append(OthersAggregateElement(value)) + choices.append(OthersAggregateElement(item, value)) else: raise DOMException( "Unknown choice kind '{kindName}'({kind}) in aggregate '{aggr}'.".format( @@ -441,4 +574,4 @@ class Aggregate(VHDLModel_Aggregate): ) ) - return cls(choices) + return cls(node, choices) diff --git a/pyGHDL/dom/InterfaceItem.py b/pyGHDL/dom/InterfaceItem.py index f720e69b4..df62c8256 100644 --- a/pyGHDL/dom/InterfaceItem.py +++ b/pyGHDL/dom/InterfaceItem.py @@ -38,13 +38,15 @@ from pyVHDLModel.VHDLModel import ( ParameterConstantInterfaceItem as VHDLModel_ParameterConstantInterfaceItem, ParameterVariableInterfaceItem as VHDLModel_ParameterVariableInterfaceItem, ParameterSignalInterfaceItem as VHDLModel_ParameterSignalInterfaceItem, + ParameterFileInterfaceItem as VHDLModel_ParameterFileInterfaceItem, Mode, SubTypeOrSymbol, Expression, ) +from pyGHDL.libghdl._types import Iir from pyGHDL.libghdl.vhdl import nodes -from pyGHDL.libghdl.vhdl.nodes import Null_Iir +from pyGHDL.dom import DOMMixin from pyGHDL.dom._Utils import GetNameOfNode, GetModeOfNode from pyGHDL.dom._Translate import GetSubTypeIndicationFromNode, GetExpressionFromNode @@ -53,132 +55,196 @@ __all__ = [] @export -class GenericConstantInterfaceItem(VHDLModel_GenericConstantInterfaceItem): +class GenericConstantInterfaceItem(VHDLModel_GenericConstantInterfaceItem, DOMMixin): + def __init__( + self, + node: Iir, + name: str, + mode: Mode, + subType: SubTypeOrSymbol, + defaultExpression: Expression, + ): + super().__init__(name=name, mode=mode) + DOMMixin.__init__(self, node) + + # TODO: move to model + self._subType = subType + self._defaultExpression = defaultExpression + @classmethod - def parse(cls, generic): - name = GetNameOfNode(generic) - mode = GetModeOfNode(generic) - subTypeIndication = GetSubTypeIndicationFromNode(generic, "generic", name) - default = nodes.Get_Default_Value(generic) + def parse(cls, genericNode: Iir) -> "GenericConstantInterfaceItem": + name = GetNameOfNode(genericNode) + mode = GetModeOfNode(genericNode) + subTypeIndication = GetSubTypeIndicationFromNode(genericNode, "generic", name) + default = nodes.Get_Default_Value(genericNode) value = GetExpressionFromNode(default) if default else None - return cls(name, mode, subTypeIndication, value) + return cls(genericNode, name, mode, subTypeIndication, value) + +@export +class PortSignalInterfaceItem(VHDLModel_PortSignalInterfaceItem, DOMMixin): def __init__( self, + node: Iir, name: str, mode: Mode, subType: SubTypeOrSymbol, - defaultExpression: Expression, + defaultExpression: Expression = None, ): super().__init__(name=name, mode=mode) + DOMMixin.__init__(self, node) + + # TODO: move to model self._subType = subType self._defaultExpression = defaultExpression - -@export -class PortSignalInterfaceItem(VHDLModel_PortSignalInterfaceItem): @classmethod - def parse(cls, port): - name = GetNameOfNode(port) - mode = GetModeOfNode(port) - subTypeIndication = GetSubTypeIndicationFromNode(port, "port", name) + def parse(cls, portNode: Iir) -> "PortSignalInterfaceItem": + name = GetNameOfNode(portNode) + mode = GetModeOfNode(portNode) + subTypeIndication = GetSubTypeIndicationFromNode(portNode, "port", name) - defaultValue = nodes.Get_Default_Value(port) + defaultValue = nodes.Get_Default_Value(portNode) value = ( - GetExpressionFromNode(defaultValue) if defaultValue != Null_Iir else None + GetExpressionFromNode(defaultValue) + if defaultValue != nodes.Null_Iir + else None ) - return cls(name, mode, subTypeIndication, value) + return cls(portNode, name, mode, subTypeIndication, value) + +@export +class ParameterConstantInterfaceItem( + VHDLModel_ParameterConstantInterfaceItem, DOMMixin +): def __init__( self, + node: Iir, name: str, mode: Mode, subType: SubTypeOrSymbol, defaultExpression: Expression = None, ): - super().__init__(name=name, mode=mode) + super().__init__(name, mode) + DOMMixin.__init__(self, node) + + # TODO: move to model self._subType = subType self._defaultExpression = defaultExpression - -@export -class ParameterConstantInterfaceItem(VHDLModel_ParameterConstantInterfaceItem): @classmethod - def parse(cls, parameter): - name = GetNameOfNode(parameter) - mode = GetModeOfNode(parameter) - subTypeIndication = GetSubTypeIndicationFromNode(parameter, "parameter", name) + def parse(cls, parameterNode: Iir) -> "ParameterConstantInterfaceItem": + name = GetNameOfNode(parameterNode) + mode = GetModeOfNode(parameterNode) + subTypeIndication = GetSubTypeIndicationFromNode( + parameterNode, "parameter", name + ) - defaultValue = nodes.Get_Default_Value(parameter) + defaultValue = nodes.Get_Default_Value(parameterNode) value = ( - GetExpressionFromNode(defaultValue) if defaultValue != Null_Iir else None + GetExpressionFromNode(defaultValue) + if defaultValue != nodes.Null_Iir + else None ) - return cls(name, mode, subTypeIndication, value) + return cls(parameterNode, name, mode, subTypeIndication, value) + +@export +class ParameterVariableInterfaceItem( + VHDLModel_ParameterVariableInterfaceItem, DOMMixin +): def __init__( self, + node: Iir, name: str, mode: Mode, subType: SubTypeOrSymbol, defaultExpression: Expression = None, ): - super().__init__(name=name, mode=mode) + super().__init__(name, mode) + DOMMixin.__init__(self, node) + + # TODO: move to model self._subType = subType self._defaultExpression = defaultExpression - -@export -class ParameterVariableInterfaceItem(VHDLModel_ParameterVariableInterfaceItem): @classmethod - def parse(cls, parameter): - name = GetNameOfNode(parameter) - mode = GetModeOfNode(parameter) - subTypeIndication = GetSubTypeIndicationFromNode(parameter, "parameter", name) + def parse(cls, parameterNode: Iir) -> "ParameterVariableInterfaceItem": + name = GetNameOfNode(parameterNode) + mode = GetModeOfNode(parameterNode) + subTypeIndication = GetSubTypeIndicationFromNode( + parameterNode, "parameter", name + ) - defaultValue = nodes.Get_Default_Value(parameter) + defaultValue = nodes.Get_Default_Value(parameterNode) value = ( - GetExpressionFromNode(defaultValue) if defaultValue != Null_Iir else None + GetExpressionFromNode(defaultValue) + if defaultValue != nodes.Null_Iir + else None ) - return cls(name, mode, subTypeIndication, value) + return cls(parameterNode, name, mode, subTypeIndication, value) + +@export +class ParameterSignalInterfaceItem(VHDLModel_ParameterSignalInterfaceItem, DOMMixin): def __init__( self, + node: Iir, name: str, mode: Mode, subType: SubTypeOrSymbol, defaultExpression: Expression = None, ): - super().__init__(name=name, mode=mode) + super().__init__(name, mode) + DOMMixin.__init__(self, node) + + # TODO: move to model self._subType = subType self._defaultExpression = defaultExpression - -@export -class ParameterSignalInterfaceItem(VHDLModel_ParameterSignalInterfaceItem): @classmethod - def parse(cls, parameter): - name = GetNameOfNode(parameter) - mode = GetModeOfNode(parameter) - subTypeIndication = GetSubTypeIndicationFromNode(parameter, "parameter", name) + def parse(cls, parameterNode: Iir) -> "ParameterSignalInterfaceItem": + name = GetNameOfNode(parameterNode) + mode = GetModeOfNode(parameterNode) + subTypeIndication = GetSubTypeIndicationFromNode( + parameterNode, "parameter", name + ) - defaultValue = nodes.Get_Default_Value(parameter) + defaultValue = nodes.Get_Default_Value(parameterNode) value = ( - GetExpressionFromNode(defaultValue) if defaultValue != Null_Iir else None + GetExpressionFromNode(defaultValue) + if defaultValue != nodes.Null_Iir + else None ) - return cls(name, mode, subTypeIndication, value) + return cls(parameterNode, name, mode, subTypeIndication, value) + +@export +class ParameterFileInterfaceItem(VHDLModel_ParameterFileInterfaceItem, DOMMixin): def __init__( self, + node: Iir, name: str, mode: Mode, subType: SubTypeOrSymbol, - defaultExpression: Expression = None, ): - super().__init__(name=name, mode=mode) + super().__init__(name, mode) + DOMMixin.__init__(self, node) + + # TODO: move to model self._subType = subType - self._defaultExpression = defaultExpression + + @classmethod + def parse(cls, parameterNode: Iir) -> "ParameterFileInterfaceItem": + name = GetNameOfNode(parameterNode) + mode = GetModeOfNode(parameterNode) + subTypeIndication = GetSubTypeIndicationFromNode( + parameterNode, "parameter", name + ) + + return cls(parameterNode, name, mode, subTypeIndication) diff --git a/pyGHDL/dom/Literal.py b/pyGHDL/dom/Literal.py index a2e86b389..784039d45 100644 --- a/pyGHDL/dom/Literal.py +++ b/pyGHDL/dom/Literal.py @@ -30,10 +30,10 @@ # # SPDX-License-Identifier: GPL-2.0-or-later # ============================================================================ -from pyGHDL.libghdl._types import Iir from pydecor import export from pyVHDLModel.VHDLModel import ( + NullLiteral as VHDLModel_NullLiteral, EnumerationLiteral as VHDLModel_EnumerationLiteral, IntegerLiteral as VHDLModel_IntegerLiteral, FloatingPointLiteral as VHDLModel_FloatingPointLiteral, @@ -43,71 +43,112 @@ from pyVHDLModel.VHDLModel import ( StringLiteral as VHDLModel_StringLiteral, ) from pyGHDL.libghdl import name_table +from pyGHDL.libghdl._types import Iir from pyGHDL.libghdl.vhdl import nodes +from pyGHDL.dom import DOMMixin from pyGHDL.dom._Utils import GetNameOfNode __all__ = [] @export -class EnumerationLiteral(VHDLModel_EnumerationLiteral): +class NullLiteral(VHDLModel_NullLiteral, DOMMixin): + def __init__(self, node: Iir): + super().__init__() + DOMMixin.__init__(self, node) + + @classmethod + def parse(cls, node: Iir) -> "NullLiteral": + return cls(node) + + +@export +class EnumerationLiteral(VHDLModel_EnumerationLiteral, DOMMixin): + def __init__(self, node: Iir, value: str): + super().__init__(value) + DOMMixin.__init__(self, node) + @classmethod def parse(cls, literalNode: Iir) -> "EnumerationLiteral": literalName = GetNameOfNode(literalNode) - return cls(literalName) + return cls(literalNode, literalName) @export -class IntegerLiteral(VHDLModel_IntegerLiteral): +class IntegerLiteral(VHDLModel_IntegerLiteral, DOMMixin): + def __init__(self, node: Iir, value: int): + super().__init__(value) + DOMMixin.__init__(self, node) + @classmethod - def parse(cls, node: Iir) -> "IntegerLiteral": - value = nodes.Get_Value(node) - return cls(value) + def parse(cls, literalNode: Iir) -> "IntegerLiteral": + value = nodes.Get_Value(literalNode) + return cls(literalNode, value) @export -class FloatingPointLiteral(VHDLModel_FloatingPointLiteral): +class FloatingPointLiteral(VHDLModel_FloatingPointLiteral, DOMMixin): + def __init__(self, node: Iir, value: float): + super().__init__(value) + DOMMixin.__init__(self, node) + @classmethod - def parse(cls, node: Iir) -> "FloatingPointLiteral": - value = nodes.Get_Fp_Value(node) - return cls(value) + def parse(cls, literalNode: Iir) -> "FloatingPointLiteral": + value = nodes.Get_Fp_Value(literalNode) + return cls(literalNode, value) @export -class PhysicalIntegerLiteral(VHDLModel_PhysicalIntegerLiteral): +class PhysicalIntegerLiteral(VHDLModel_PhysicalIntegerLiteral, DOMMixin): + def __init__(self, node: Iir, value: int, unitName: str): + super().__init__(value, unitName) + DOMMixin.__init__(self, node) + @classmethod - def parse(cls, node: Iir) -> "PhysicalIntegerLiteral": - value = nodes.Get_Value(node) - unit = nodes.Get_Unit_Name(node) + def parse(cls, literalNode: Iir) -> "PhysicalIntegerLiteral": + value = nodes.Get_Value(literalNode) + unit = nodes.Get_Unit_Name(literalNode) unitName = GetNameOfNode(unit) - return cls(value, unitName) + return cls(literalNode, value, unitName) @export -class PhysicalFloatingLiteral(VHDLModel_PhysicalFloatingLiteral): +class PhysicalFloatingLiteral(VHDLModel_PhysicalFloatingLiteral, DOMMixin): + def __init__(self, node: Iir, value: int, unitName: float): + super().__init__(value, unitName) + DOMMixin.__init__(self, node) + @classmethod - def parse(cls, node: Iir) -> "PhysicalFloatingLiteral": - value = nodes.Get_Fp_Value(node) - unit = nodes.Get_Unit_Name(node) + def parse(cls, literalNode: Iir) -> "PhysicalFloatingLiteral": + value = nodes.Get_Fp_Value(literalNode) + unit = nodes.Get_Unit_Name(literalNode) unitName = GetNameOfNode(unit) - return cls(value, unitName) + return cls(literalNode, value, unitName) @export -class CharacterLiteral(VHDLModel_CharacterLiteral): +class CharacterLiteral(VHDLModel_CharacterLiteral, DOMMixin): + def __init__(self, node: Iir, value: str): + super().__init__(value) + DOMMixin.__init__(self, node) + @classmethod - def parse(cls, node: Iir) -> "CharacterLiteral": - identifier = nodes.Get_Identifier(node) + def parse(cls, literalNode: Iir) -> "CharacterLiteral": + identifier = nodes.Get_Identifier(literalNode) value = name_table.Get_Character(identifier) - return cls(value) + return cls(literalNode, value) @export -class StringLiteral(VHDLModel_StringLiteral): +class StringLiteral(VHDLModel_StringLiteral, DOMMixin): + def __init__(self, node: Iir, value: str): + super().__init__(value) + DOMMixin.__init__(self, node) + @classmethod - def parse(cls, node: Iir) -> "StringLiteral": - stringID = nodes.Get_String8_Id(node) + def parse(cls, literalNode: Iir) -> "StringLiteral": + stringID = nodes.Get_String8_Id(literalNode) value = name_table.Get_Name_Ptr(stringID) - return cls(value) + return cls(literalNode, value) diff --git a/pyGHDL/dom/Misc.py b/pyGHDL/dom/Misc.py index 8bea6cf61..b80c64a82 100644 --- a/pyGHDL/dom/Misc.py +++ b/pyGHDL/dom/Misc.py @@ -40,36 +40,24 @@ from pydecor import export from pyVHDLModel.VHDLModel import ( Alias as VHDLModel_Alias, ) +from pyGHDL.libghdl._types import Iir +from pyGHDL.dom._Utils import GetNameOfNode +from pyGHDL.dom import DOMMixin __all__ = [] @export -class Position: - _filename: str - _line: int - _column: int - - def __init__(self, filename: str, line: int, column: int): - self._filename = filename - self._line = line - self._column = column - - @property - def Filename(self): - return self._filename - - @property - def Line(self): - return self._line +class Alias(VHDLModel_Alias, DOMMixin): + def __init__(self, node: Iir, aliasName: str): + super().__init__(aliasName) + DOMMixin.__init__(self, node) - @property - def Column(self): - return self._column + @classmethod + def parse(cls, node: Iir): + aliasName = GetNameOfNode(node) + # FIXME: add an implementation -@export -class Alias(VHDLModel_Alias): - def __init__(self, aliasName: str): - super().__init__(aliasName) + return cls(node, aliasName) diff --git a/pyGHDL/dom/Names.py b/pyGHDL/dom/Names.py new file mode 100644 index 000000000..fa53acae6 --- /dev/null +++ b/pyGHDL/dom/Names.py @@ -0,0 +1,99 @@ +# ============================================================================= +# ____ _ _ ____ _ _ +# _ __ _ _ / ___| | | | _ \| | __| | ___ _ __ ___ +# | '_ \| | | | | _| |_| | | | | | / _` |/ _ \| '_ ` _ \ +# | |_) | |_| | |_| | _ | |_| | |___ | (_| | (_) | | | | | | +# | .__/ \__, |\____|_| |_|____/|_____(_)__,_|\___/|_| |_| |_| +# |_| |___/ +# ============================================================================= +# 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 typing import List + +from pyGHDL.libghdl._types import Iir +from pydecor import export + +from pyVHDLModel.VHDLModel import ( + SimpleName as VHDLModel_SimpleName, + ParenthesisName as VHDLModel_ParenthesisName, + IndexedName as VHDLModel_IndexedName, + SlicedName as VHDLModel_SlicedName, + SelectedName as VHDLModel_SelectedName, + AttributeName as VHDLModel_AttributeName, + AllName as VHDLModel_AllName, + Name, +) +from pyGHDL.dom import DOMMixin + +__all__ = [] + + +@export +class SimpleName(VHDLModel_SimpleName, DOMMixin): + def __init__(self, node: Iir, name: str): + super().__init__(name) + DOMMixin.__init__(self, node) + + +@export +class ParenthesisName(VHDLModel_ParenthesisName, DOMMixin): + def __init__(self, node: Iir, prefix: Name, associations: List): + super().__init__(prefix, associations) + DOMMixin.__init__(self, node) + + +@export +class IndexedName(VHDLModel_IndexedName, DOMMixin): + def __init__(self, node: Iir, name: str): + super().__init__(name) + DOMMixin.__init__(self, node) + + +@export +class SlicedName(VHDLModel_SlicedName, DOMMixin): + def __init__(self, node: Iir, name: str): + super().__init__(name) + DOMMixin.__init__(self, node) + + +@export +class SelectedName(VHDLModel_SelectedName, DOMMixin): + def __init__(self, node: Iir, name: str, prefix: Name): + super().__init__(name, prefix) + DOMMixin.__init__(self, node) + + +@export +class AttributeName(VHDLModel_AttributeName, DOMMixin): + def __init__(self, node: Iir, name: str, prefix: Name): + super().__init__(name, prefix) + DOMMixin.__init__(self, node) + + +@export +class AllName(VHDLModel_AllName, DOMMixin): + def __init__(self, node: Iir, prefix: Name): + super().__init__(prefix) + DOMMixin.__init__(self, node) diff --git a/pyGHDL/dom/NonStandard.py b/pyGHDL/dom/NonStandard.py index 9e2950f03..1524b549f 100644 --- a/pyGHDL/dom/NonStandard.py +++ b/pyGHDL/dom/NonStandard.py @@ -35,6 +35,8 @@ .. todo:: Add a module documentation. """ +import ctypes +import time from pathlib import Path from typing import Any @@ -56,10 +58,11 @@ from pyGHDL.libghdl import ( errorout_memory, LibGHDLException, utils, + files_map_editor, ) from pyGHDL.libghdl.vhdl import nodes, sem_lib, parse +from pyGHDL.dom import DOMException from pyGHDL.dom._Utils import GetIirKindOfNode, CheckForErrors -from pyGHDL.dom.Common import DOMException from pyGHDL.dom.DesignUnit import ( Entity, Architecture, @@ -67,6 +70,7 @@ from pyGHDL.dom.DesignUnit import ( PackageBody, Context, Configuration, + PackageInstantiation, ) __all__ = [] @@ -104,33 +108,62 @@ class Library(VHDLModel_Library): @export class Document(VHDLModel_Document): + _filename: Path __ghdlFileID: Any __ghdlSourceFileEntry: Any __ghdlFile: Any - def __init__(self, path: Path = None, dontParse: bool = False): + __ghdlProcessingTime: float + __domTranslateTime: float + + def __init__( + self, + path: Path, + sourceCode: str = None, + dontParse: bool = False, + dontTranslate: bool = False, + ): super().__init__(path) - self.__ghdl_init() - if dontParse == False: - self.parse() + self._filename = path - 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 - ) - if self.__ghdlSourceFileEntry == files_map.No_Source_File_Entry: - raise LibGHDLException("Cannot load file '{!s}'".format(self.Path)) + if sourceCode is None: + self.__loadFromPath() + else: + self.__loadFromString(sourceCode) - CheckForErrors() + if dontParse == False: + # Parse input file + t1 = time.perf_counter() + self.__ghdlFile = sem_lib.Load_File(self.__ghdlSourceFileEntry) + CheckForErrors() + self.__ghdlProcessingTime = time.perf_counter() - t1 + + if dontTranslate == False: + t1 = time.perf_counter() + self.translate() + self.__domTranslateTime = time.perf_counter() - t1 + + def __loadFromPath(self): + with self._filename.open("r", encoding="utf-8") as file: + self.__loadFromString(file.read()) + + def __loadFromString(self, sourceCode: str): + sourcesBytes = sourceCode.encode("utf-8") + sourceLength = len(sourcesBytes) + bufferLength = sourceLength + 128 + self.__ghdlFileID = name_table.Get_Identifier(str(self._filename)) + dirId = name_table.Null_Identifier + self.__ghdlSourceFileEntry = files_map.Reserve_Source_File( + dirId, self.__ghdlFileID, bufferLength + ) + files_map_editor.Fill_Text( + self.__ghdlSourceFileEntry, ctypes.c_char_p(sourcesBytes), sourceLength + ) - # Parse input file - self.__ghdlFile = sem_lib.Load_File(self.__ghdlSourceFileEntry) CheckForErrors() - def parse(self): + def translate(self): firstUnit = nodes.Get_First_Design_Unit(self.__ghdlFile) for unit in utils.chain_iter(firstUnit): @@ -153,6 +186,10 @@ class Document(VHDLModel_Document): packageBody = PackageBody.parse(libraryUnit) self.PackageBodies.append(packageBody) + elif nodeKind == nodes.Iir_Kind.Package_Instantiation_Declaration: + package = PackageInstantiation.parse(libraryUnit) + self.Packages.append(package) + elif nodeKind == nodes.Iir_Kind.Context_Declaration: context = Context.parse(libraryUnit) self.Contexts.append(context) @@ -167,3 +204,11 @@ class Document(VHDLModel_Document): kindName=nodeKind.name, kind=nodeKind ) ) + + @property + def LibGHDLProcessingTime(self) -> float: + return self.__ghdlProcessingTime + + @property + def DOMTranslationTime(self) -> float: + return self.__domTranslateTime diff --git a/pyGHDL/dom/Object.py b/pyGHDL/dom/Object.py index a5ea4b1ff..3085f9f81 100644 --- a/pyGHDL/dom/Object.py +++ b/pyGHDL/dom/Object.py @@ -30,114 +30,183 @@ # # SPDX-License-Identifier: GPL-2.0-or-later # ============================================================================ -from pyGHDL.libghdl.vhdl import nodes +from typing import Union + +from pyGHDL.libghdl._types import Iir from pydecor import export -from pyGHDL.dom._Translate import GetSubTypeIndicationFromNode, GetExpressionFromNode -from pyGHDL.dom._Utils import GetNameOfNode from pyVHDLModel.VHDLModel import ( Constant as VHDLModel_Constant, DeferredConstant as VHDLModel_DeferredConstant, Variable as VHDLModel_Variable, SharedVariable as VHDLModel_SharedVariable, Signal as VHDLModel_Signal, + File as VHDLModel_File, Expression, SubTypeOrSymbol, ) +from pyGHDL.libghdl.vhdl import nodes +from pyGHDL.dom import DOMMixin +from pyGHDL.dom._Utils import GetNameOfNode + __all__ = [] @export -class Constant(VHDLModel_Constant): +class Constant(VHDLModel_Constant, DOMMixin): def __init__( - self, name: str, subType: SubTypeOrSymbol, defaultExpression: Expression + self, + node: Iir, + name: str, + subType: SubTypeOrSymbol, + defaultExpression: Expression, ): super().__init__(name) + DOMMixin.__init__(self, node) self._name = name self._subType = subType self._defaultExpression = defaultExpression @classmethod - def parse(cls, node): - name = GetNameOfNode(node) - subTypeIndication = GetSubTypeIndicationFromNode(node, "constant", name) - defaultExpression = GetExpressionFromNode(nodes.Get_Default_Value(node)) + def parse(cls, constantNode: Iir) -> Union["Constant", "DeferredConstant"]: + from pyGHDL.dom._Translate import ( + GetSubTypeIndicationFromNode, + GetExpressionFromNode, + ) - return cls(name, subTypeIndication, defaultExpression) + name = GetNameOfNode(constantNode) + subTypeIndication = GetSubTypeIndicationFromNode(constantNode, "constant", name) + defaultValue = nodes.Get_Default_Value(constantNode) + if defaultValue != nodes.Null_Iir: + defaultExpression = GetExpressionFromNode(defaultValue) + + return cls(constantNode, name, subTypeIndication, defaultExpression) + else: + return DeferredConstant(constantNode, name, subTypeIndication) @export -class DeferredConstant(VHDLModel_DeferredConstant): - def __init__(self, name: str, subType: SubTypeOrSymbol): +class DeferredConstant(VHDLModel_DeferredConstant, DOMMixin): + def __init__(self, node: Iir, name: str, subType: SubTypeOrSymbol): super().__init__(name) + DOMMixin.__init__(self, node) self._name = name self._subType = subType @classmethod - def parse(cls, node): - name = GetNameOfNode(node) + def parse(cls, constantNode: Iir) -> "DeferredConstant": + from pyGHDL.dom._Translate import GetSubTypeIndicationFromNode + + name = GetNameOfNode(constantNode) subTypeIndication = GetSubTypeIndicationFromNode( - node, "deferred constant", name + constantNode, "deferred constant", name ) - return cls(name, subTypeIndication) + return cls(constantNode, name, subTypeIndication) @export -class Variable(VHDLModel_Variable): +class Variable(VHDLModel_Variable, DOMMixin): def __init__( - self, name: str, subType: SubTypeOrSymbol, defaultExpression: Expression + self, + node: Iir, + name: str, + subType: SubTypeOrSymbol, + defaultExpression: Expression, ): super().__init__(name) + DOMMixin.__init__(self, node) self._name = name self._subType = subType self._defaultExpression = defaultExpression @classmethod - def parse(cls, node): - name = GetNameOfNode(node) - subTypeIndication = GetSubTypeIndicationFromNode(node, "variable", name) - defaultExpression = GetExpressionFromNode(nodes.Get_Default_Value(node)) + def parse(cls, variableNode: Iir) -> "Variable": + from pyGHDL.dom._Translate import ( + GetSubTypeIndicationFromNode, + GetExpressionFromNode, + ) - return cls(name, subTypeIndication, defaultExpression) + name = GetNameOfNode(variableNode) + subTypeIndication = GetSubTypeIndicationFromNode(variableNode, "variable", name) + defaultValue = nodes.Get_Default_Value(variableNode) + defaultExpression = None + if defaultValue != nodes.Null_Iir: + defaultExpression = GetExpressionFromNode(defaultValue) + + return cls(variableNode, name, subTypeIndication, defaultExpression) @export -class SharedVariable(VHDLModel_SharedVariable): - def __init__(self, name: str, subType: SubTypeOrSymbol): +class SharedVariable(VHDLModel_SharedVariable, DOMMixin): + def __init__(self, node: Iir, name: str, subType: SubTypeOrSymbol): super().__init__(name) + DOMMixin.__init__(self, node) self._name = name self._subType = subType @classmethod - def parse(cls, node): - name = GetNameOfNode(node) - subTypeIndication = GetSubTypeIndicationFromNode(node, "variable", name) + def parse(cls, variableNode: Iir) -> "SharedVariable": + from pyGHDL.dom._Translate import GetSubTypeIndicationFromNode + + name = GetNameOfNode(variableNode) + subTypeIndication = GetSubTypeIndicationFromNode(variableNode, "variable", name) - return cls(name, subTypeIndication) + return cls(variableNode, name, subTypeIndication) @export -class Signal(VHDLModel_Signal): +class Signal(VHDLModel_Signal, DOMMixin): def __init__( - self, name: str, subType: SubTypeOrSymbol, defaultExpression: Expression + self, + node: Iir, + name: str, + subType: SubTypeOrSymbol, + defaultExpression: Expression, ): super().__init__(name) + DOMMixin.__init__(self, node) self._name = name self._subType = subType self._defaultExpression = defaultExpression @classmethod - def parse(cls, node): - name = GetNameOfNode(node) - subTypeIndication = GetSubTypeIndicationFromNode(node, "signal", name) - default = nodes.Get_Default_Value(node) + def parse(cls, signalNode: Iir) -> "Signal": + from pyGHDL.dom._Translate import ( + GetSubTypeIndicationFromNode, + GetExpressionFromNode, + ) + + name = GetNameOfNode(signalNode) + subTypeIndication = GetSubTypeIndicationFromNode(signalNode, "signal", name) + default = nodes.Get_Default_Value(signalNode) defaultExpression = GetExpressionFromNode(default) if default else None - return cls(name, subTypeIndication, defaultExpression) + return cls(signalNode, name, subTypeIndication, defaultExpression) + + +@export +class File(VHDLModel_File, DOMMixin): + def __init__(self, node: Iir, name: str, subType: SubTypeOrSymbol): + super().__init__(name) + DOMMixin.__init__(self, node) + + self._name = name + self._subType = subType + + @classmethod + def parse(cls, fileNode: Iir) -> "File": + from pyGHDL.dom._Translate import GetSubTypeIndicationFromNode + + name = GetNameOfNode(fileNode) + subTypeIndication = GetSubTypeIndicationFromNode(fileNode, "file", name) + + # FIXME: handle file open stuff + + return cls(fileNode, name, subTypeIndication) diff --git a/pyGHDL/dom/Range.py b/pyGHDL/dom/Range.py index 1a5ac518c..d091be1c6 100644 --- a/pyGHDL/dom/Range.py +++ b/pyGHDL/dom/Range.py @@ -50,11 +50,3 @@ class Range(VHDLModel_Range): 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/Subprogram.py b/pyGHDL/dom/Subprogram.py index 0f10ebf62..42e3c7d79 100644 --- a/pyGHDL/dom/Subprogram.py +++ b/pyGHDL/dom/Subprogram.py @@ -32,11 +32,8 @@ # ============================================================================ from typing import List -from pyGHDL.dom.Symbol import SimpleSubTypeSymbol -from pyGHDL.libghdl.vhdl import nodes from pydecor import export -from pyGHDL.dom._Utils import GetNameOfNode from pyVHDLModel.VHDLModel import ( Function as VHDLModel_Function, Procedure as VHDLModel_Procedure, @@ -45,19 +42,26 @@ from pyVHDLModel.VHDLModel import ( ParameterInterfaceItem, ) from pyGHDL.libghdl._types import Iir +from pyGHDL.libghdl.vhdl import nodes +from pyGHDL.dom import DOMMixin +from pyGHDL.dom._Utils import GetNameOfNode +from pyGHDL.dom.Symbol import SimpleSubTypeSymbol @export -class Function(VHDLModel_Function): +class Function(VHDLModel_Function, DOMMixin): def __init__( self, + node: Iir, functionName: str, returnType: SubTypeOrSymbol, genericItems: List[GenericInterfaceItem] = None, parameterItems: List[ParameterInterfaceItem] = None, ): super().__init__(functionName) + DOMMixin.__init__(self, node) + # TODO: move to model self._genericItems = [] if genericItems is None else [g for g in genericItems] self._parameterItems = ( [] if parameterItems is None else [p for p in parameterItems] @@ -65,53 +69,56 @@ class Function(VHDLModel_Function): self._returnType = returnType @classmethod - def parse(cls, node: Iir): + def parse(cls, functionNode: Iir) -> "Function": from pyGHDL.dom._Translate import ( GetGenericsFromChainedNodes, GetParameterFromChainedNodes, ) - functionName = GetNameOfNode(node) + functionName = GetNameOfNode(functionNode) - generics = GetGenericsFromChainedNodes(nodes.Get_Generic_Chain(node)) + generics = GetGenericsFromChainedNodes(nodes.Get_Generic_Chain(functionNode)) parameters = GetParameterFromChainedNodes( - nodes.Get_Interface_Declaration_Chain(node) + nodes.Get_Interface_Declaration_Chain(functionNode) ) - returnType = nodes.Get_Return_Type_Mark(node) + returnType = nodes.Get_Return_Type_Mark(functionNode) returnTypeName = GetNameOfNode(returnType) - returnTypeSymbol = SimpleSubTypeSymbol(returnTypeName) + returnTypeSymbol = SimpleSubTypeSymbol(returnType, returnTypeName) - return cls(functionName, returnTypeSymbol, generics, parameters) + return cls(functionNode, functionName, returnTypeSymbol, generics, parameters) @export -class Procedure(VHDLModel_Procedure): +class Procedure(VHDLModel_Procedure, DOMMixin): def __init__( self, + node: Iir, procedureName: str, genericItems: List[GenericInterfaceItem] = None, parameterItems: List[ParameterInterfaceItem] = None, ): super().__init__(procedureName) + DOMMixin.__init__(self, node) + # TODO: move to model self._genericItems = [] if genericItems is None else [g for g in genericItems] self._parameterItems = ( [] if parameterItems is None else [p for p in parameterItems] ) @classmethod - def parse(cls, node: Iir): + def parse(cls, procedureNode: Iir) -> "Procedure": from pyGHDL.dom._Translate import ( GetGenericsFromChainedNodes, GetParameterFromChainedNodes, ) - procedureName = GetNameOfNode(node) + procedureName = GetNameOfNode(procedureNode) - generics = GetGenericsFromChainedNodes(nodes.Get_Generic_Chain(node)) + generics = GetGenericsFromChainedNodes(nodes.Get_Generic_Chain(procedureNode)) parameters = GetParameterFromChainedNodes( - nodes.Get_Interface_Declaration_Chain(node) + nodes.Get_Interface_Declaration_Chain(procedureNode) ) - return cls(procedureName, generics, parameters) + return cls(procedureNode, procedureName, generics, parameters) diff --git a/pyGHDL/dom/Symbol.py b/pyGHDL/dom/Symbol.py index d6d348f14..85d1c637b 100644 --- a/pyGHDL/dom/Symbol.py +++ b/pyGHDL/dom/Symbol.py @@ -31,9 +31,9 @@ # SPDX-License-Identifier: GPL-2.0-or-later # ============================================================================ from typing import List, Iterator + from pydecor import export -from pyGHDL.dom.Range import Range from pyVHDLModel.VHDLModel import ( EntitySymbol as VHDLModel_EntitySymbol, SimpleSubTypeSymbol as VHDLModel_SimpleSubTypeSymbol, @@ -43,91 +43,91 @@ from pyVHDLModel.VHDLModel import ( SimpleObjectOrFunctionCallSymbol as VHDLModel_SimpleObjectOrFunctionCallSymbol, IndexedObjectOrFunctionCallSymbol as VHDLModel_IndexedObjectOrFunctionCallSymbol, Constraint, + Name, ) +from pyGHDL.libghdl._types import Iir +from pyGHDL.dom import DOMMixin +from pyGHDL.dom._Utils import GetNameOfNode +from pyGHDL.dom.Range import Range -from pyGHDL.libghdl import utils -from pyGHDL.libghdl.vhdl import nodes -from pyGHDL.dom._Utils import GetIirKindOfNode, GetNameOfNode -from pyGHDL.dom.Common import DOMException __all__ = [] @export -class EntitySymbol(VHDLModel_EntitySymbol): - def __init__(self, entityName: str): +class EntitySymbol(VHDLModel_EntitySymbol, DOMMixin): + def __init__(self, node: Iir, entityName: str): super().__init__(entityName) + DOMMixin.__init__(self, node) @export -class EnumerationLiteralSymbol(VHDLModel_EnumerationLiteralSymbol): - def __init__(self, literalName: str): +class EnumerationLiteralSymbol(VHDLModel_EnumerationLiteralSymbol, DOMMixin): + def __init__(self, node: Iir, literalName: str): super().__init__(symbolName=literalName) + DOMMixin.__init__(self, node) @export -class SimpleSubTypeSymbol(VHDLModel_SimpleSubTypeSymbol): - def __init__(self, subTypeName: str): +class SimpleSubTypeSymbol(VHDLModel_SimpleSubTypeSymbol, DOMMixin): + def __init__(self, node: Iir, subTypeName: Name): if isinstance(subTypeName, (List, Iterator)): subTypeName = ".".join(subTypeName) super().__init__(subTypeName=subTypeName) + DOMMixin.__init__(self, node) @export -class ConstrainedScalarSubTypeSymbol(VHDLModel_ConstrainedScalarSubTypeSymbol): - def __init__(self, subTypeName: str, range: Range = None): +class ConstrainedScalarSubTypeSymbol( + VHDLModel_ConstrainedScalarSubTypeSymbol, DOMMixin +): + def __init__(self, node: Iir, subTypeName: str, range: Range = None): super().__init__(subTypeName=subTypeName, range=range) + DOMMixin.__init__(self, node) @classmethod - def parse(cls, node): + def parse(cls, node: Iir): pass @export -class ConstrainedCompositeSubTypeSymbol(VHDLModel_ConstrainedCompositeSubTypeSymbol): - def __init__(self, subTypeName: str, constraints: List[Constraint] = None): +class ConstrainedCompositeSubTypeSymbol( + VHDLModel_ConstrainedCompositeSubTypeSymbol, DOMMixin +): + def __init__( + self, node: Iir, subTypeName: str, constraints: List[Constraint] = None + ): super().__init__(subTypeName=subTypeName, constraints=constraints) + DOMMixin.__init__(self, node) @classmethod - def parse(cls, node): + def parse(cls, node: Iir): pass @export -class SimpleObjectOrFunctionCallSymbol(VHDLModel_SimpleObjectOrFunctionCallSymbol): +class SimpleObjectOrFunctionCallSymbol( + VHDLModel_SimpleObjectOrFunctionCallSymbol, DOMMixin +): @classmethod - def parse(cls, node): + def parse(cls, node: Iir): name = GetNameOfNode(node) return cls(name) @export -class IndexedObjectOrFunctionCallSymbol(VHDLModel_IndexedObjectOrFunctionCallSymbol): - def __init__(self, name: str, associations: List): +class IndexedObjectOrFunctionCallSymbol( + VHDLModel_IndexedObjectOrFunctionCallSymbol, DOMMixin +): + def __init__(self, node: Iir, name: str): super().__init__(objectName=name) + DOMMixin.__init__(self, node) @classmethod - def parse(cls, node): - from pyGHDL.dom._Translate import GetExpressionFromNode - - prefix = nodes.Get_Prefix(node) - name = GetNameOfNode(prefix) - - associations = [] - for item in utils.chain_iter(nodes.Get_Association_Chain(node)): - kind = GetIirKindOfNode(item) - - if kind == nodes.Iir_Kind.Association_Element_By_Expression: - actual = nodes.Get_Actual(item) - expr = GetExpressionFromNode(actual) + def parse(cls, node: Iir): + from pyGHDL.dom._Translate import GetExpressionFromNode, GetNameFromNode - associations.append(expr) - else: - raise DOMException( - "Unknown association kind '{kindName}'({kind}) in array index/slice or function call '{node}'.".format( - kind=kind, kindName=kind.name, node=node - ) - ) + name = GetNameFromNode(node) - return cls(name, associations) + return cls(node, name) diff --git a/pyGHDL/dom/Type.py b/pyGHDL/dom/Type.py index 2875f1bc2..db51f1c49 100644 --- a/pyGHDL/dom/Type.py +++ b/pyGHDL/dom/Type.py @@ -30,38 +30,41 @@ # # SPDX-License-Identifier: GPL-2.0-or-later # ============================================================================ -from pyGHDL.dom.Common import DOMException -from pyGHDL.dom.Literal import EnumerationLiteral -from pyGHDL.dom._Utils import GetNameOfNode, GetIirKindOfNode -from pyGHDL.libghdl import utils - -from pyGHDL.libghdl.vhdl import nodes +from typing import List, Union, Iterator, Tuple -from pyGHDL.libghdl._types import Iir from pydecor import export -from pyGHDL.dom.Range import Range from pyVHDLModel.VHDLModel import ( + PhysicalType as VHDLModel_PhysicalType, IntegerType as VHDLModel_IntegerType, EnumeratedType as VHDLModel_EnumeratedType, ArrayType as VHDLModel_ArrayType, RecordTypeElement as VHDLModel_RecordTypeElement, RecordType as VHDLModel_RecordType, AccessType as VHDLModel_AccessType, + FileType as VHDLModel_FileType, + ProtectedType as VHDLModel_ProtectedType, + ProtectedTypeBody as VHDLModel_ProtectedTypeBody, SubType as VHDLModel_SubType, + SubTypeOrSymbol, ) +from pyGHDL.libghdl import utils +from pyGHDL.libghdl._types import Iir +from pyGHDL.libghdl.vhdl import nodes +from pyGHDL.dom import DOMMixin, DOMException +from pyGHDL.dom._Utils import GetNameOfNode, GetIirKindOfNode +from pyGHDL.dom.Symbol import SimpleSubTypeSymbol +from pyGHDL.dom.Literal import EnumerationLiteral, PhysicalIntegerLiteral +from pyGHDL.dom.Range import Range +from pyGHDL.dom.Subprogram import Function, Procedure @export -class IntegerType(VHDLModel_IntegerType): - def __init__(self, typeName: str, range: Range): - super().__init__(typeName) - self._leftBound = range.LeftBound - self._rightBound = range.RightBound - +class EnumeratedType(VHDLModel_EnumeratedType, DOMMixin): + def __init__(self, node: Iir, name: str, literals: List[EnumerationLiteral]): + super().__init__(name, literals) + DOMMixin.__init__(self, node) -@export -class EnumeratedType(VHDLModel_EnumeratedType): @classmethod def parse(cls, typeName: str, typeDefinitionNode: Iir) -> "EnumeratedType": literals = [] @@ -70,11 +73,59 @@ class EnumeratedType(VHDLModel_EnumeratedType): literal = EnumerationLiteral.parse(enumerationLiteral) literals.append(literal) - return cls(typeName, literals) + return cls(typeDefinitionNode, typeName, literals) + + +@export +class IntegerType(VHDLModel_IntegerType, DOMMixin): + def __init__(self, node: Iir, typeName: str, range: Range): + super().__init__(typeName) + DOMMixin.__init__(self, node) + + self._leftBound = range.LeftBound + self._rightBound = range.RightBound + + +@export +class PhysicalType(VHDLModel_PhysicalType, DOMMixin): + def __init__( + self, + node: Iir, + typeName: str, + primaryUnit: str, + units: List[Tuple[str, PhysicalIntegerLiteral]], + ): + super().__init__(typeName, primaryUnit, units) + DOMMixin.__init__(self, node) + + @classmethod + def parse(cls, typeName: str, typeDefinitionNode: Iir) -> "PhysicalType": + primaryUnit = nodes.Get_Primary_Unit(typeDefinitionNode) + primaryUnitName = GetNameOfNode(primaryUnit) + + units = [] + for secondaryUnit in utils.chain_iter(nodes.Get_Unit_Chain(typeDefinitionNode)): + secondaryUnitName = GetNameOfNode(secondaryUnit) + if secondaryUnit == primaryUnit: + continue + + physicalLiteral = PhysicalIntegerLiteral.parse( + nodes.Get_Physical_Literal(secondaryUnit) + ) + + units.append((secondaryUnitName, physicalLiteral)) + + return cls(typeDefinitionNode, typeName, primaryUnitName, units) @export -class ArrayType(VHDLModel_ArrayType): +class ArrayType(VHDLModel_ArrayType, DOMMixin): + def __init__( + self, node: Iir, name: str, indices: List, elementSubType: SubTypeOrSymbol + ): + super().__init__(name, indices, elementSubType) + DOMMixin.__init__(self, node) + @classmethod def parse(cls, typeName: str, typeDefinitionNode: Iir) -> "ArrayType": from pyGHDL.dom._Translate import ( @@ -103,11 +154,15 @@ class ArrayType(VHDLModel_ArrayType): elementSubTypeIndication, "array declaration", typeName ) - return cls(typeName, indices, elementSubType) + return cls(typeDefinitionNode, typeName, indices, elementSubType) @export -class RecordTypeElement(VHDLModel_RecordTypeElement): +class RecordTypeElement(VHDLModel_RecordTypeElement, DOMMixin): + def __init__(self, node: Iir, name: str, subType: SubTypeOrSymbol): + super().__init__(name, subType) + DOMMixin.__init__(self, node) + @classmethod def parse(cls, elementDeclarationNode: Iir) -> "RecordTypeElement": from pyGHDL.dom._Translate import GetSubTypeIndicationFromNode @@ -117,11 +172,15 @@ class RecordTypeElement(VHDLModel_RecordTypeElement): elementDeclarationNode, "record element", elementName ) - return cls(elementName, elementType) + return cls(elementDeclarationNode, elementName, elementType) @export -class RecordType(VHDLModel_RecordType): +class RecordType(VHDLModel_RecordType, DOMMixin): + def __init__(self, node: Iir, name: str, elements: List[RecordTypeElement] = None): + super().__init__(name, elements) + DOMMixin.__init__(self, node) + @classmethod def parse(cls, typeName: str, typeDefinitionNode: Iir) -> "RecordType": elements = [] @@ -130,11 +189,57 @@ class RecordType(VHDLModel_RecordType): element = RecordTypeElement.parse(elementDeclaration) elements.append(element) - return cls(typeName, elements) + return cls(typeDefinitionNode, typeName, elements) @export -class AccessType(VHDLModel_AccessType): +class ProtectedType(VHDLModel_ProtectedType, DOMMixin): + def __init__(self, node: Iir, name: str, methods: Union[List, Iterator] = None): + super().__init__(name, methods) + DOMMixin.__init__(self, node) + + @classmethod + def parse(cls, typeName: str, typeDefinitionNode: Iir) -> "ProtectedType": + # FIXME: change this to a generator + methods = [] + for item in utils.chain_iter(nodes.Get_Declaration_Chain(typeDefinitionNode)): + kind = GetIirKindOfNode(item) + if kind == nodes.Iir_Kind.Function_Declaration: + methods.append(Function.parse(item)) + elif kind == nodes.Iir_Kind.Procedure_Declaration: + methods.append(Procedure.parse(item)) + + return cls(typeDefinitionNode, typeName, methods) + + +@export +class ProtectedTypeBody(VHDLModel_ProtectedTypeBody, DOMMixin): + def __init__( + self, node: Iir, name: str, declaredItems: Union[List, Iterator] = None + ): + super().__init__(name, declaredItems) + DOMMixin.__init__(self, node) + + @classmethod + def parse(cls, protectedBodyNode: Iir) -> "ProtectedTypeBody": + from pyGHDL.dom._Translate import GetDeclaredItemsFromChainedNodes + + typeName = GetNameOfNode(protectedBodyNode) + declaredItems = GetDeclaredItemsFromChainedNodes( + nodes.Get_Declaration_Chain(protectedBodyNode), + "protected type body", + typeName, + ) + + return cls(protectedBodyNode, typeName, declaredItems) + + +@export +class AccessType(VHDLModel_AccessType, DOMMixin): + def __init__(self, node: Iir, name: str, designatedSubType: SubTypeOrSymbol): + super().__init__(name, designatedSubType) + DOMMixin.__init__(self, node) + @classmethod def parse(cls, typeName: str, typeDefinitionNode: Iir) -> "AccessType": from pyGHDL.dom._Translate import GetSubTypeIndicationFromIndicationNode @@ -146,10 +251,29 @@ class AccessType(VHDLModel_AccessType): designatedSubtypeIndication, "access type", typeName ) - return cls(typeName, designatedSubType) + return cls(typeDefinitionNode, typeName, designatedSubType) + + +@export +class FileType(VHDLModel_FileType, DOMMixin): + def __init__(self, node: Iir, name: str, designatedSubType: SubTypeOrSymbol): + super().__init__(name, designatedSubType) + DOMMixin.__init__(self, node) + + @classmethod + def parse(cls, typeName: str, typeDefinitionNode: Iir) -> "FileType": + + designatedSubTypeMark = nodes.Get_File_Type_Mark(typeDefinitionNode) + designatedSubTypeName = GetNameOfNode(designatedSubTypeMark) + designatedSubType = SimpleSubTypeSymbol( + typeDefinitionNode, designatedSubTypeName + ) + + return cls(typeDefinitionNode, typeName, designatedSubType) @export -class SubType(VHDLModel_SubType): - def __init__(self, subtypeName: str): +class SubType(VHDLModel_SubType, DOMMixin): + def __init__(self, node: Iir, subtypeName: str): super().__init__(subtypeName) + DOMMixin.__init__(self, node) diff --git a/pyGHDL/dom/_Translate.py b/pyGHDL/dom/_Translate.py index cb9448f09..502a94ad3 100644 --- a/pyGHDL/dom/_Translate.py +++ b/pyGHDL/dom/_Translate.py @@ -34,6 +34,8 @@ from typing import List, Generator from pydecor import export +from pyGHDL.dom import Position, DOMException +from pyGHDL.dom.Object import Variable from pyVHDLModel.VHDLModel import ( Constraint, Direction, @@ -44,6 +46,7 @@ from pyVHDLModel.VHDLModel import ( PortInterfaceItem, ParameterInterfaceItem, ModelEntity, + Name, ) from pyGHDL.libghdl import utils @@ -52,10 +55,14 @@ from pyGHDL.libghdl.vhdl import nodes from pyGHDL.dom._Utils import ( GetNameOfNode, GetIirKindOfNode, - GetPositionOfNode, - GetSelectedName, ) -from pyGHDL.dom.Common import DOMException +from pyGHDL.dom.Names import ( + SimpleName, + SelectedName, + AttributeName, + ParenthesisName, + AllName, +) from pyGHDL.dom.Symbol import ( SimpleObjectOrFunctionCallSymbol, SimpleSubTypeSymbol, @@ -69,10 +76,13 @@ from pyGHDL.dom.Type import ( ArrayType, RecordType, EnumeratedType, - RecordTypeElement, AccessType, + ProtectedType, + ProtectedTypeBody, + FileType, + PhysicalType, ) -from pyGHDL.dom.Range import Range, RangeExpression +from pyGHDL.dom.Range import Range from pyGHDL.dom.Literal import ( IntegerLiteral, CharacterLiteral, @@ -80,7 +90,7 @@ from pyGHDL.dom.Literal import ( StringLiteral, PhysicalIntegerLiteral, PhysicalFloatingLiteral, - EnumerationLiteral, + NullLiteral, ) from pyGHDL.dom.Expression import ( SubtractionExpression, @@ -114,6 +124,7 @@ from pyGHDL.dom.Expression import ( ShiftRightArithmeticExpression, RotateLeftExpression, RotateRightExpression, + RangeExpression, ) from pyGHDL.dom.Subprogram import Function, Procedure from pyGHDL.dom.Misc import Alias @@ -123,6 +134,52 @@ __all__ = [] @export +def GetNameFromNode(node: Iir) -> Name: + kind = GetIirKindOfNode(node) + if kind == nodes.Iir_Kind.Simple_Name: + name = GetNameOfNode(node) + return SimpleName(node, name) + elif kind == nodes.Iir_Kind.Selected_Name: + name = GetNameOfNode(node) + prefixName = GetNameFromNode(nodes.Get_Prefix(node)) + return SelectedName(node, name, prefixName) + elif kind == nodes.Iir_Kind.Attribute_Name: + name = GetNameOfNode(node) + prefixName = GetNameFromNode(nodes.Get_Prefix(node)) + return AttributeName(node, name, prefixName) + elif kind == nodes.Iir_Kind.Parenthesis_Name: + prefixName = GetNameFromNode(nodes.Get_Prefix(node)) + associations = GetAssociations(node) + + return ParenthesisName(node, prefixName, associations) + elif kind == nodes.Iir_Kind.Selected_By_All_Name: + prefixName = GetNameFromNode(nodes.Get_Prefix(node)) + return AllName(node, prefixName) + else: + raise DOMException("Unknown name kind '{kind}'".format(kind=kind.name)) + + +def GetAssociations(node: Iir) -> List: + associations = [] + for item in utils.chain_iter(nodes.Get_Association_Chain(node)): + kind = GetIirKindOfNode(item) + + if kind == nodes.Iir_Kind.Association_Element_By_Expression: + actual = nodes.Get_Actual(item) + expr = GetExpressionFromNode(actual) + + associations.append(expr) + else: + raise DOMException( + "Unknown association kind '{kindName}'({kind}) in array index/slice or function call '{node}'.".format( + kind=kind, kindName=kind.name, node=node + ) + ) + + return associations + + +@export def GetArrayConstraintsFromSubtypeIndication( subTypeIndication: Iir, ) -> List[Constraint]: @@ -132,22 +189,19 @@ def GetArrayConstraintsFromSubtypeIndication( ): constraintKind = GetIirKindOfNode(constraint) if constraintKind == nodes.Iir_Kind.Range_Expression: - constraints.append(RangeExpression(GetRangeFromNode(constraint))) - elif constraintKind == nodes.Iir_Kind.Attribute_Name: - name = GetNameOfNode(constraint) - prefix = nodes.Get_Prefix(constraint) - name2 = GetNameOfNode(prefix) - kind2 = GetIirKindOfNode(prefix) - print(name2, kind2, name) - - raise DOMException("[NOT IMPLEMENTED] Attribute name as range.") - elif constraintKind == nodes.Iir_Kind.Simple_Name: - raise DOMException("[NOT IMPLEMENTED] Subtype as range.") + constraints.append(RangeExpression.parse(constraint)) + elif constraintKind in ( + nodes.Iir_Kind.Simple_Name, + nodes.Iir_Kind.Parenthesis_Name, + nodes.Iir_Kind.Selected_Name, + nodes.Iir_Kind.Attribute_Name, + ): + constraints.append(GetNameFromNode(constraint)) else: - position = GetPositionOfNode(constraint) + position = Position.parse(constraint) raise DOMException( "Unknown constraint kind '{kind}' for constraint '{constraint}' in subtype indication '{indication}' at {file}:{line}:{column}.".format( - kind=constraintKind, + kind=constraintKind.name, constraint=constraint, indication=subTypeIndication, file=position.Filename, @@ -168,21 +222,27 @@ def GetTypeFromNode(node: Iir) -> BaseType: if kind == nodes.Iir_Kind.Range_Expression: r = GetRangeFromNode(typeDefinition) - return IntegerType(typeName, r) + return IntegerType(node, typeName, r) + elif kind == nodes.Iir_Kind.Physical_Type_Definition: + return PhysicalType.parse(typeName, typeDefinition) elif kind == nodes.Iir_Kind.Enumeration_Type_Definition: return EnumeratedType.parse(typeName, typeDefinition) elif kind == nodes.Iir_Kind.Array_Type_Definition: return ArrayType.parse(typeName, typeDefinition) elif kind == nodes.Iir_Kind.Array_Subtype_Definition: - print("Array_Subtype_Definition") + print("[NOT IMPLEMENTED] Array_Subtype_Definition") - return ArrayType + return ArrayType(typeDefinition, "????", [], None) elif kind == nodes.Iir_Kind.Record_Type_Definition: return RecordType.parse(typeName, typeDefinition) elif kind == nodes.Iir_Kind.Access_Type_Definition: return AccessType.parse(typeName, typeDefinition) + elif kind == nodes.Iir_Kind.File_Type_Definition: + return FileType.parse(typeName, typeDefinition) + elif kind == nodes.Iir_Kind.Protected_Type_Declaration: + return ProtectedType.parse(typeName, typeDefinition) else: - position = GetPositionOfNode(typeDefinition) + position = Position.parse(typeDefinition) raise DOMException( "Unknown type definition kind '{kindName}'({kind}) for type '{name}' at {file}:{line}:{column}.".format( kind=kind, @@ -207,10 +267,19 @@ def GetSubTypeIndicationFromNode(node: Iir, entity: str, name: str) -> SubTypeOr def GetSubTypeIndicationFromIndicationNode( subTypeIndicationNode: Iir, entity: str, name: str ) -> SubTypeOrSymbol: + if subTypeIndicationNode is nodes.Null_Iir: + print( + "[NOT IMPLEMENTED]: Unhandled multiple declarations for {entity} '{name}'.".format( + entity=entity, name=name + ) + ) + return None kind = GetIirKindOfNode(subTypeIndicationNode) - if kind == nodes.Iir_Kind.Simple_Name: - return GetSimpleTypeFromNode(subTypeIndicationNode) - elif kind == nodes.Iir_Kind.Selected_Name: + if kind in ( + nodes.Iir_Kind.Simple_Name, + nodes.Iir_Kind.Selected_Name, + nodes.Iir_Kind.Attribute_Name, + ): return GetSimpleTypeFromNode(subTypeIndicationNode) elif kind == nodes.Iir_Kind.Subtype_Definition: return GetScalarConstrainedSubTypeFromNode(subTypeIndicationNode) @@ -226,8 +295,8 @@ def GetSubTypeIndicationFromIndicationNode( @export def GetSimpleTypeFromNode(subTypeIndicationNode: Iir) -> SimpleSubTypeSymbol: - subTypeName = GetSelectedName(subTypeIndicationNode) - return SimpleSubTypeSymbol(subTypeName) + subTypeName = GetNameFromNode(subTypeIndicationNode) + return SimpleSubTypeSymbol(subTypeIndicationNode, subTypeName) @export @@ -238,7 +307,7 @@ def GetScalarConstrainedSubTypeFromNode( typeMarkName = GetNameOfNode(typeMark) rangeConstraint = nodes.Get_Range_Constraint(subTypeIndicationNode) r = GetRangeFromNode(rangeConstraint) - return ConstrainedScalarSubTypeSymbol(typeMarkName, r) + return ConstrainedScalarSubTypeSymbol(subTypeIndicationNode, typeMarkName, r) @export @@ -249,14 +318,16 @@ def GetCompositeConstrainedSubTypeFromNode( typeMarkName = GetNameOfNode(typeMark) constraints = GetArrayConstraintsFromSubtypeIndication(subTypeIndicationNode) - return ConstrainedCompositeSubTypeSymbol(typeMarkName, constraints) + return ConstrainedCompositeSubTypeSymbol( + subTypeIndicationNode, typeMarkName, constraints + ) @export -def GetSubTypeFromNode(node: Iir) -> SubTypeOrSymbol: - subTypeName = GetNameOfNode(node) +def GetSubTypeFromNode(subTypeNode: Iir) -> SubTypeOrSymbol: + subTypeName = GetNameOfNode(subTypeNode) - return SubType(subTypeName) + return SubType(subTypeNode, subTypeName) @export @@ -274,7 +345,10 @@ def GetRangeFromNode(node: Iir) -> Range: __EXPRESSION_TRANSLATION = { nodes.Iir_Kind.Simple_Name: SimpleObjectOrFunctionCallSymbol, + nodes.Iir_Kind.Selected_Name: IndexedObjectOrFunctionCallSymbol, + nodes.Iir_Kind.Attribute_Name: IndexedObjectOrFunctionCallSymbol, nodes.Iir_Kind.Parenthesis_Name: IndexedObjectOrFunctionCallSymbol, + nodes.Iir_Kind.Null_Literal: NullLiteral, nodes.Iir_Kind.Integer_Literal: IntegerLiteral, nodes.Iir_Kind.Floating_Point_Literal: FloatingPointLiteral, nodes.Iir_Kind.Physical_Int_Literal: PhysicalIntegerLiteral, @@ -282,6 +356,7 @@ __EXPRESSION_TRANSLATION = { nodes.Iir_Kind.Character_Literal: CharacterLiteral, nodes.Iir_Kind.String_Literal8: StringLiteral, nodes.Iir_Kind.Negation_Operator: NegationExpression, + nodes.Iir_Kind.Range_Expression: RangeExpression, nodes.Iir_Kind.Addition_Operator: AdditionExpression, nodes.Iir_Kind.Concatenation_Operator: ConcatenationExpression, nodes.Iir_Kind.Not_Operator: InverseExpression, @@ -322,7 +397,7 @@ def GetExpressionFromNode(node: Iir) -> Expression: try: cls = __EXPRESSION_TRANSLATION[kind] except KeyError: - position = GetPositionOfNode(node) + position = Position.parse(node) raise DOMException( "Unknown expression kind '{kindName}'({kind}) in expression '{expr}' at {file}:{line}:{column}.".format( kind=kind, @@ -346,11 +421,17 @@ def GetGenericsFromChainedNodes( if kind == nodes.Iir_Kind.Interface_Constant_Declaration: from pyGHDL.dom.InterfaceItem import GenericConstantInterfaceItem - genericConstant = GenericConstantInterfaceItem.parse(generic) - - yield genericConstant + yield GenericConstantInterfaceItem.parse(generic) + elif kind == nodes.Iir_Kind.Interface_Type_Declaration: + print("[NOT IMPLEMENTED] generic type") + elif kind == nodes.Iir_Kind.Interface_Package_Declaration: + print("[NOT IMPLEMENTED] generic package") + elif kind == nodes.Iir_Kind.Interface_Procedure_Declaration: + print("[NOT IMPLEMENTED] generic procedure") + elif kind == nodes.Iir_Kind.Interface_Function_Declaration: + print("[NOT IMPLEMENTED] generic function") else: - position = GetPositionOfNode(generic) + position = Position.parse(generic) raise DOMException( "Unknown generic kind '{kindName}'({kind}) in generic '{generic}' at {file}:{line}:{column}.".format( kind=kind, @@ -376,7 +457,7 @@ def GetPortsFromChainedNodes( yield portSignal else: - position = GetPositionOfNode(port) + position = Position.parse(port) raise DOMException( "Unknown port kind '{kindName}'({kind}) in port '{port}' at {file}:{line}:{column}.".format( kind=kind, @@ -407,8 +488,12 @@ def GetParameterFromChainedNodes( from pyGHDL.dom.InterfaceItem import ParameterSignalInterfaceItem yield ParameterSignalInterfaceItem.parse(parameter) + elif kind == nodes.Iir_Kind.Interface_File_Declaration: + from pyGHDL.dom.InterfaceItem import ParameterFileInterfaceItem + + yield ParameterFileInterfaceItem.parse(parameter) else: - position = GetPositionOfNode(parameter) + position = Position.parse(parameter) raise DOMException( "Unknown parameter kind '{kindName}'({kind}) in parameter '{param}' at {file}:{line}:{column}.".format( kind=kind, @@ -437,11 +522,16 @@ def GetDeclaredItemsFromChainedNodes( if nodes.Get_Shared_Flag(item): yield SharedVariable.parse(item) else: - raise DOMException("Found non-shared variable.") + yield Variable.parse(item) + # raise DOMException("Found non-shared variable.") elif kind == nodes.Iir_Kind.Signal_Declaration: from pyGHDL.dom.Object import Signal yield Signal.parse(item) + elif kind == nodes.Iir_Kind.File_Declaration: + from pyGHDL.dom.Object import File + + yield File.parse(item) elif kind == nodes.Iir_Kind.Type_Declaration: yield GetTypeFromNode(item) elif kind == nodes.Iir_Kind.Anonymous_Type_Declaration: @@ -458,18 +548,41 @@ def GetDeclaredItemsFromChainedNodes( elif kind == nodes.Iir_Kind.Procedure_Body: # procedureName = NodeToName(item) print("found procedure body '{name}'".format(name="????")) + elif kind == nodes.Iir_Kind.Protected_Type_Body: + yield ProtectedTypeBody.parse(item) elif kind == nodes.Iir_Kind.Object_Alias_Declaration: yield GetAliasFromNode(item) elif kind == nodes.Iir_Kind.Component_Declaration: from pyGHDL.dom.DesignUnit import Component yield Component.parse(item) + elif kind == nodes.Iir_Kind.Attribute_Declaration: + from pyGHDL.dom.Attribute import Attribute + + yield Attribute.parse(item) + elif kind == nodes.Iir_Kind.Attribute_Specification: + from pyGHDL.dom.Attribute import AttributeSpecification + + yield AttributeSpecification.parse(item) + elif kind == nodes.Iir_Kind.Use_Clause: + from pyGHDL.dom.DesignUnit import UseClause + + yield UseClause.parse(item) + elif kind == nodes.Iir_Kind.Package_Instantiation_Declaration: + from pyGHDL.dom.DesignUnit import PackageInstantiation + + yield PackageInstantiation.parse(item) + elif kind == nodes.Iir_Kind.Configuration_Specification: + print( + "[NOT IMPLEMENTED] Configuration specification in {name}".format( + name=name + ) + ) else: - position = GetPositionOfNode(item) + position = Position.parse(item) raise DOMException( - "Unknown declared item kind '{kindName}'({kind}) in {entity} '{name}' at {file}:{line}:{column}.".format( - kind=kind, - kindName=kind.name, + "Unknown declared item kind '{kind}' in {entity} '{name}' at {file}:{line}:{column}.".format( + kind=kind.name, entity=entity, name=name, file=position.Filename, @@ -479,7 +592,7 @@ def GetDeclaredItemsFromChainedNodes( ) -def GetAliasFromNode(node: Iir): - aliasName = GetNameOfNode(node) +def GetAliasFromNode(aliasNode: Iir): + aliasName = GetNameOfNode(aliasNode) - return Alias(aliasName) + return Alias(aliasNode, aliasName) diff --git a/pyGHDL/dom/_Utils.py b/pyGHDL/dom/_Utils.py index 1c109c9dc..2b17d98ab 100644 --- a/pyGHDL/dom/_Utils.py +++ b/pyGHDL/dom/_Utils.py @@ -32,15 +32,13 @@ # ============================================================================ from pydecor import export -from pyGHDL.dom.Common import DOMException from pyVHDLModel.VHDLModel import Mode from pyGHDL.libghdl import LibGHDLException, name_table, files_map, errorout_memory from pyGHDL.libghdl.vhdl import nodes from pyGHDL.libghdl.vhdl.nodes import Null_Iir from pyGHDL.libghdl._types import Iir -from pyGHDL.dom.Misc import Position - +from pyGHDL.dom import DOMException __all__ = [] @@ -60,7 +58,8 @@ def CheckForErrors() -> None: if errorCount != 0: for i in range(errorCount): rec = errorout_memory.Get_Error_Record(i + 1) - fileName = name_table.Get_Name_Ptr(files_map.Get_File_Name(rec.file)) + # FIXME: needs help from @tgingold + fileName = "" # name_table.Get_Name_Ptr(files_map.Get_File_Name(rec.file)) message = errorout_memory.Get_Error_Message(i + 1) errors.append( @@ -77,9 +76,8 @@ def CheckForErrors() -> None: @export def GetIirKindOfNode(node: Iir) -> nodes.Iir_Kind: """Return the kind of a node in the IIR tree.""" - if node == Null_Iir: - raise ValueError("Parameter 'node' must not be 'Null_iir'.") + raise ValueError("GetIirKindOfNode: Parameter 'node' must not be 'Null_iir'.") kind: int = nodes.Get_Kind(node) return nodes.Iir_Kind(kind) @@ -88,56 +86,20 @@ def GetIirKindOfNode(node: Iir) -> nodes.Iir_Kind: @export def GetNameOfNode(node: Iir) -> str: """Return the python string from node :obj:`node` identifier.""" - if node == Null_Iir: - raise ValueError("Parameter 'node' must not be 'Null_iir'.") + raise ValueError("GetNameOfNode: Parameter 'node' must not be 'Null_iir'.") identifier = nodes.Get_Identifier(node) return name_table.Get_Name_Ptr(identifier) @export -def GetSelectedName(node: Iir): - names = [] - kind = GetIirKindOfNode(node) - if kind == nodes.Iir_Kind.Simple_Name: - return GetNameOfNode(node) - - while kind != nodes.Iir_Kind.Simple_Name: - names.append(GetNameOfNode(node)) - node = nodes.Get_Prefix(node) - kind = GetIirKindOfNode(node) - - names.append(GetNameOfNode(node)) - - return reversed(names) - - -@export def GetModeOfNode(node: Iir) -> Mode: """Return the mode of a :obj:`node`.""" - if node == Null_Iir: - raise ValueError("Parameter 'node' must not be 'Null_iir'.") + raise ValueError("GetModeOfNode: Parameter 'node' must not be 'Null_iir'.") try: return __MODE_TRANSLATION[nodes.Get_Mode(node)] except KeyError: raise LibGHDLException("Unknown mode.") - - -@export -def GetPositionOfNode(node: Iir) -> Position: - """Return the source code position of a IIR node.""" - - if node == Null_Iir: - raise ValueError("Parameter 'node' must not be 'Null_iir'.") - - location = nodes.Get_Location(node) - file = files_map.Location_To_File(location) - fileName = name_table.Get_Name_Ptr(files_map.Get_File_Name(file)) - # position = files_map.Location_File_To_Pos(location, file) - line = files_map.Location_File_To_Line(location, file) - column = files_map.Location_File_Line_To_Offset(location, file, line) - - return Position(fileName, line, column) diff --git a/pyGHDL/dom/__init__.py b/pyGHDL/dom/__init__.py index b4ffaf4c6..19f23a94b 100644 --- a/pyGHDL/dom/__init__.py +++ b/pyGHDL/dom/__init__.py @@ -30,5 +30,78 @@ # # SPDX-License-Identifier: GPL-2.0-or-later # ============================================================================ +from pathlib import Path + +from pyGHDL import GHDLBaseException +from pyGHDL.libghdl import files_map, name_table + +from pyGHDL.libghdl.vhdl import nodes +from pydecor import export + +from pyGHDL.libghdl._types import Iir __all__ = [] + + +@export +class Position: + """Represents the source code position of a IIR node in a source file.""" + + _filename: Path + _line: int + _column: int + + def __init__(self, filename: Path, line: int, column: int): + self._filename = filename + self._line = line + self._column = column + + @classmethod + def parse(cls, node: Iir) -> "Position": + """Return the source code position of a IIR node.""" + if node == nodes.Null_Iir: + raise ValueError( + "Position.parse(): Parameter 'node' must not be 'Null_iir'." + ) + + location = nodes.Get_Location(node) + file = files_map.Location_To_File(location) + fileNameId = files_map.Get_File_Name(file) + fileName = name_table.Get_Name_Ptr(fileNameId) + line = files_map.Location_File_To_Line(location, file) + column = files_map.Location_File_Line_To_Offset(location, file, line) + + return cls(Path(fileName), line, column) + + @property + def Filename(self) -> Path: + return self._filename + + @property + def Line(self) -> int: + return self._line + + @property + def Column(self) -> int: + return self._column + + +@export +class DOMMixin: + _iirNode: Iir + _position: Position = None + + def __init__(self, node: Iir): + self._iirNode = node + + @property + def Position(self) -> Position: + if self._position is None: + self._position = Position.parse(self._iirNode) + + return self._position + + +@export +class DOMException(GHDLBaseException): + pass diff --git a/pyGHDL/dom/formatting/prettyprint.py b/pyGHDL/dom/formatting/prettyprint.py index 10def8503..f055f3f51 100644 --- a/pyGHDL/dom/formatting/prettyprint.py +++ b/pyGHDL/dom/formatting/prettyprint.py @@ -2,6 +2,7 @@ from typing import List, Union from pydecor import export +from pyGHDL.dom.Attribute import Attribute, AttributeSpecification from pyGHDL.dom.Misc import Alias from pyGHDL.dom.Subprogram import Procedure from pyGHDL.dom.Type import ( @@ -11,6 +12,10 @@ from pyGHDL.dom.Type import ( RecordType, AccessType, EnumeratedType, + FileType, + ProtectedType, + ProtectedTypeBody, + PhysicalType, ) from pyVHDLModel.VHDLModel import ( GenericInterfaceItem, @@ -32,8 +37,10 @@ from pyGHDL.dom.DesignUnit import ( Configuration, Context, Component, + UseClause, + PackageInstantiation, ) -from pyGHDL.dom.Object import Constant, Signal, SharedVariable +from pyGHDL.dom.Object import Constant, Signal, SharedVariable, File from pyGHDL.dom.InterfaceItem import ( GenericConstantInterfaceItem, PortSignalInterfaceItem, @@ -139,7 +146,15 @@ class PrettyPrint: def formatEntity(self, entity: Entity, level: int = 0) -> StringBuffer: buffer = [] prefix = " " * level - buffer.append("{prefix}- Name: {name}".format(name=entity.Name, prefix=prefix)) + buffer.append( + "{prefix}- Name: {name} at {file}:{line}:{column}".format( + name=entity.Name, + prefix=prefix, + file=entity.Position.Filename.name, + line=entity.Position.Line, + column=entity.Position.Column, + ) + ) buffer.append("{prefix} Generics:".format(prefix=prefix)) for generic in entity.GenericItems: for line in self.formatGeneric(generic, level + 1): @@ -161,7 +176,13 @@ class PrettyPrint: buffer = [] prefix = " " * level buffer.append( - "{prefix}- Name: {name}".format(name=architecture.Name, prefix=prefix) + "{prefix}- Name: {name} at {file}:{line}:{column}".format( + name=architecture.Name, + prefix=prefix, + file=architecture.Position.Filename.name, + line=architecture.Position.Line, + column=architecture.Position.Column, + ) ) buffer.append( "{prefix} Entity: {entity}".format( @@ -334,6 +355,16 @@ class PrettyPrint: else "", ) ) + elif isinstance(item, File): + buffer.append( + "{prefix}- File {name} : {subtype}".format( + prefix=prefix, + name=item.Name, + subtype=self.formatSubtypeIndication( + item.SubType, "file", item.Name + ), + ) + ) elif isinstance(item, Type): buffer.append( "{prefix}- {type}".format(prefix=prefix, type=self.formatType(item)) @@ -368,6 +399,32 @@ class PrettyPrint: elif isinstance(item, Component): for line in self.formatComponent(item, level): buffer.append(line) + elif isinstance(item, Attribute): + buffer.append( + "{prefix}- attribute {name} : {type!s}".format( + prefix=prefix, name=item.Name, type=item.SubType + ) + ) + elif isinstance(item, AttributeSpecification): + buffer.append( + "{prefix}- attribute {name!s} of {entity} : {entityClass} is {value}".format( + prefix=prefix, + name=item.Attribute, + entity="????", + entityClass="????", + value="????", + ) + ) + elif isinstance(item, UseClause): + buffer.append( + "{prefix}- use {name!s}".format(prefix=prefix, name=item.Item) + ) + elif isinstance(item, PackageInstantiation): + buffer.append( + "{prefix}- package {name} is new {name2!s} generic map (.....)".format( + prefix=prefix, name=item.Name, name2=item.PackageReference + ) + ) else: raise PrettyPrintException( "Unhandled declared item kind '{name}'.".format( @@ -385,12 +442,20 @@ class PrettyPrint: ) elif isinstance(item, EnumeratedType): result += "(........)" + elif isinstance(item, PhysicalType): + result += " is range ....... units ..... end units" elif isinstance(item, ArrayType): result += "array(........) of ....." elif isinstance(item, RecordType): result += "record ..... end record" elif isinstance(item, AccessType): result += "access ....." + elif isinstance(item, FileType): + result += "file ....." + elif isinstance(item, ProtectedType): + result += "protected ..... end protected" + elif isinstance(item, ProtectedTypeBody): + result += "protected body ..... end protected body" else: raise PrettyPrintException( "Unknown type '{name}'".format(name=item.__class__.__name__) @@ -402,11 +467,12 @@ class PrettyPrint: if isinstance(subTypeIndication, SimpleSubTypeSymbol): return "{type}".format(type=subTypeIndication.SymbolName) elif isinstance(subTypeIndication, ConstrainedCompositeSubTypeSymbol): - ranges = [str(c.Range) for c in subTypeIndication.Constraints] - constraints = ", ".join(ranges) + constraints = [] + for constraint in subTypeIndication.Constraints: + constraints.append(str(constraint)) return "{type}({constraints})".format( - type=subTypeIndication.SymbolName, constraints=constraints + type=subTypeIndication.SymbolName, constraints=", ".join(constraints) ) else: raise PrettyPrintException( diff --git a/pyGHDL/libghdl/__init__.py b/pyGHDL/libghdl/__init__.py index 525710590..d23ffc0e7 100644 --- a/pyGHDL/libghdl/__init__.py +++ b/pyGHDL/libghdl/__init__.py @@ -87,7 +87,7 @@ def _check_libghdl_bindir(bindir: Path, basename: Path) -> Path: def _get_libghdl_path(): - """ + """\ Locate the directory where the shared library is installed. Search order: @@ -182,7 +182,7 @@ def initialize() -> None: @export # @BindToLibGHDL("libghdl__set_option") def set_option(Opt: str) -> bool: - """ + """\ Set option :obj:`opt`. :param Opt: Option to set. @@ -195,7 +195,7 @@ def set_option(Opt: str) -> bool: @export # @BindToLibGHDL("libghdl__analyze_init") def analyze_init() -> None: - """ + """\ Initialize the analyzer. .. deprecated:: 1.0.0 @@ -207,7 +207,7 @@ def analyze_init() -> None: @export # @BindToLibGHDL("libghdl__analyze_init_status") def analyze_init_status() -> int: - """ + """\ Initialize the analyzer. :return: Returns 0 in case of success. @@ -218,7 +218,7 @@ def analyze_init_status() -> int: @export # @BindToLibGHDL("libghdl__analyze_file") def analyze_file(fname: str) -> Iir: - """ + """\ Analyze a given filename :obj:`fname`. :param fname: File name diff --git a/pyGHDL/libghdl/_decorator.py b/pyGHDL/libghdl/_decorator.py index a680cc9d1..9c5aefa19 100644 --- a/pyGHDL/libghdl/_decorator.py +++ b/pyGHDL/libghdl/_decorator.py @@ -48,7 +48,7 @@ from typing import Callable, List, Dict, Any, TypeVar from pydecor import export -from pyGHDL.libghdl import libghdl +from pyGHDL.libghdl import libghdl, LibGHDLException @export @@ -181,14 +181,34 @@ def BindToLibGHDL(subprogramName): @wraps(func) def inner(*args): - return returnType(functionPointer(*args)) + try: + returnValue = functionPointer(*args) + except OSError as ex: + errors = [str(ex)] + raise LibGHDLException( + "Caught exception when calling '{func}' in libghdl.".format( + func=subprogramName + ), + errors, + ) from ex + + return returnType(returnValue) return inner else: @wraps(func) def inner(*args): - return functionPointer(*args) + try: + return functionPointer(*args) + except OSError as ex: + errors = [str(ex)] + raise LibGHDLException( + "Caught exception when calling '{func}' in libghdl.".format( + func=subprogramName + ), + errors, + ) from ex return inner diff --git a/pyGHDL/libghdl/files_map_editor.py b/pyGHDL/libghdl/files_map_editor.py index eceb3efe2..2009af882 100644 --- a/pyGHDL/libghdl/files_map_editor.py +++ b/pyGHDL/libghdl/files_map_editor.py @@ -32,7 +32,7 @@ # SPDX-License-Identifier: GPL-2.0-or-later # ============================================================================ -from ctypes import c_int32, c_char_p, c_bool +from ctypes import c_int32, c_char_p, c_bool, c_uint32 from pydecor import export @@ -113,7 +113,7 @@ def Fill_Text(File: SourceFileEntry, Text_Pointer, Text_Length: int) -> None: @export # @BindToLibGHDL("files_map__editor__check_buffer_content") def Check_Buffer_Content( - File: SourceFileEntry, String_Pointer, String_Length: int + File: SourceFileEntry, String_Pointer: c_char_p, String_Length: c_uint32 ) -> None: """ Check that content of :obj:`File` is STR[1 .. STR_LEN]. diff --git a/pyGHDL/requirements.txt b/pyGHDL/requirements.txt index 6198d8044..974fef2ed 100644 --- a/pyGHDL/requirements.txt +++ b/pyGHDL/requirements.txt @@ -1,3 +1,3 @@ pydecor>=2.0.1 -pyVHDLModel==0.10.3 +pyVHDLModel==0.10.4 #https://github.com/VHDL/pyVHDLModel/archive/dev.zip#pyVHDLModel |