diff options
-rwxr-xr-x | pyGHDL/cli/DOM.py | 21 | ||||
-rw-r--r-- | pyGHDL/dom/DesignUnit.py | 77 | ||||
-rw-r--r-- | pyGHDL/dom/Expression.py | 84 | ||||
-rw-r--r-- | pyGHDL/dom/InterfaceItem.py | 115 | ||||
-rw-r--r-- | pyGHDL/dom/Literal.py | 40 | ||||
-rw-r--r-- | pyGHDL/dom/Misc.py | 136 | ||||
-rw-r--r-- | pyGHDL/dom/NonStandard.py | 172 | ||||
-rw-r--r-- | pyGHDL/dom/Object.py | 8 | ||||
-rw-r--r-- | pyGHDL/dom/Subprogram.py | 99 | ||||
-rw-r--r-- | pyGHDL/dom/Symbol.py | 47 | ||||
-rw-r--r-- | pyGHDL/dom/Type.py | 53 | ||||
-rw-r--r-- | pyGHDL/dom/_Translate.py | 266 | ||||
-rw-r--r-- | pyGHDL/dom/_Utils.py | 22 | ||||
-rw-r--r-- | pyGHDL/dom/formatting/prettyprint.py | 70 | ||||
-rw-r--r-- | pyGHDL/requirements.txt | 2 | ||||
-rw-r--r-- | testsuite/pyunit/Current.vhdl | 4 | ||||
-rw-r--r-- | testsuite/pyunit/dom/Expressions.py | 8 | ||||
-rw-r--r-- | testsuite/pyunit/dom/Literals.py | 2 | ||||
-rw-r--r-- | testsuite/pyunit/dom/SimpleEntity.py | 2 | ||||
-rw-r--r-- | testsuite/pyunit/dom/SimplePackage.py | 2 |
20 files changed, 958 insertions, 272 deletions
diff --git a/pyGHDL/cli/DOM.py b/pyGHDL/cli/DOM.py index d7ffc7319..2b846edde 100755 --- a/pyGHDL/cli/DOM.py +++ b/pyGHDL/cli/DOM.py @@ -7,24 +7,25 @@ from pathlib import Path from pydecor import export -from pyGHDL.dom import Misc -from pyGHDL import GHDLBaseException +from pyGHDL.dom import NonStandard __all__ = [] __api__ = __all__ -from pyGHDL.dom.formatting.prettyprint import PrettyPrint +from pyGHDL.dom.Common import DOMException + +from pyGHDL.dom.formatting.prettyprint import PrettyPrint, PrettyPrintException @export class Application: - _design: Misc.Design + _design: NonStandard.Design def __init__(self): - self._design = Misc.Design() + self._design = NonStandard.Design() def addFile(self, filename: Path, library: str): - document = Misc.Document(filename) + document = NonStandard.Document(filename) self._design.Documents.append(document) def prettyPrint(self): @@ -45,15 +46,17 @@ def main(items): if len(items) < 1: print("Please, provide the files to be analyzed as CLI arguments.") print("Using <testsuite/pyunit/SimpleEntity.vhdl> for demo purposes.\n") - items = ["testsuite/pyunit/SimpleEntity.vhdl"] + items = ["testsuite/pyunit/Current.vhdl"] for item in items: try: app = Application() app.addFile(Path(item), "default_lib") app.prettyPrint() - except GHDLBaseException as ex: - print(ex) + except DOMException as ex: + print("DOM:", ex) + except PrettyPrintException as ex: + print("PP:", ex) _exitcode = 1 return _exitcode diff --git a/pyGHDL/dom/DesignUnit.py b/pyGHDL/dom/DesignUnit.py index 534149677..ce93bda3e 100644 --- a/pyGHDL/dom/DesignUnit.py +++ b/pyGHDL/dom/DesignUnit.py @@ -39,24 +39,28 @@ This module contains all DOM classes for VHDL's design units (:class:`context <E """ +from pyGHDL.libghdl._types import Iir from pydecor import export -from pyGHDL.dom.Symbol import EntitySymbol -from pyVHDLModel.VHDLModel import Entity as VHDLModel_Entity, EntityOrSymbol -from pyVHDLModel.VHDLModel import Architecture as VHDLModel_Architecture -from pyVHDLModel.VHDLModel import Package as VHDLModel_Package -from pyVHDLModel.VHDLModel import PackageBody as VHDLModel_PackageBody -from pyVHDLModel.VHDLModel import Context as VHDLModel_Context -from pyVHDLModel.VHDLModel import Configuration as VHDLModel_Configuration +from pyVHDLModel.VHDLModel import ( + Entity as VHDLModel_Entity, + EntityOrSymbol, + Architecture as VHDLModel_Architecture, + Package as VHDLModel_Package, + PackageBody as VHDLModel_PackageBody, + Context as VHDLModel_Context, + Configuration as VHDLModel_Configuration, + Component as VHDLModel_Component, +) from pyGHDL.libghdl.vhdl import nodes - -from pyGHDL.dom._Utils import NodeToName +from pyGHDL.dom._Utils import GetNameOfNode from pyGHDL.dom._Translate import ( GetGenericsFromChainedNodes, GetPortsFromChainedNodes, GetDeclaredItemsFromChainedNodes, ) +from pyGHDL.dom.Symbol import EntitySymbol from pyGHDL.dom.Common import GHDLMixin @@ -66,20 +70,18 @@ __all__ = [] @export class Entity(VHDLModel_Entity, GHDLMixin): @classmethod - def parse(cls, libraryUnit): - name = NodeToName(libraryUnit) + def parse(cls, entityNode: Iir): + name = GetNameOfNode(entityNode) entity = cls(name) - for generic in GetGenericsFromChainedNodes( - nodes.Get_Generic_Chain(libraryUnit) - ): + for generic in GetGenericsFromChainedNodes(nodes.Get_Generic_Chain(entityNode)): entity.GenericItems.append(generic) - for port in GetPortsFromChainedNodes(nodes.Get_Port_Chain(libraryUnit)): + for port in GetPortsFromChainedNodes(nodes.Get_Port_Chain(entityNode)): entity.PortItems.append(port) for item in GetDeclaredItemsFromChainedNodes( - nodes.Get_Declaration_Chain(libraryUnit), "entity", name + nodes.Get_Declaration_Chain(entityNode), "entity", name ): entity.DeclaredItems.append(item) @@ -94,15 +96,15 @@ class Architecture(VHDLModel_Architecture, GHDLMixin): self._entity = entity @classmethod - def parse(cls, libraryUnit): - name = NodeToName(libraryUnit) - entityName = NodeToName(nodes.Get_Entity_Name(libraryUnit)) + def parse(cls, architectureNode: Iir): + name = GetNameOfNode(architectureNode) + entityName = GetNameOfNode(nodes.Get_Entity_Name(architectureNode)) entity = EntitySymbol(entityName) architecture = cls(name, entity) for item in GetDeclaredItemsFromChainedNodes( - nodes.Get_Declaration_Chain(libraryUnit), "architecture", name + nodes.Get_Declaration_Chain(architectureNode), "architecture", name ): architecture.DeclaredItems.append(item) @@ -113,10 +115,29 @@ class Architecture(VHDLModel_Architecture, GHDLMixin): @export +class Component(VHDLModel_Component): + @classmethod + def parse(cls, componentNode: Iir): + name = GetNameOfNode(componentNode) + + component = cls(name) + + for generic in GetGenericsFromChainedNodes( + nodes.Get_Generic_Chain(componentNode) + ): + component.GenericItems.append(generic) + + for port in GetPortsFromChainedNodes(nodes.Get_Port_Chain(componentNode)): + component.PortItems.append(port) + + return component + + +@export class Package(VHDLModel_Package, GHDLMixin): @classmethod - def parse(cls, libraryUnit): - name = NodeToName(libraryUnit) + def parse(cls, libraryUnit: Iir): + name = GetNameOfNode(libraryUnit) package = cls(name) @@ -131,8 +152,8 @@ class Package(VHDLModel_Package, GHDLMixin): @export class PackageBody(VHDLModel_PackageBody, GHDLMixin): @classmethod - def parse(cls, libraryUnit): - name = NodeToName(libraryUnit) + def parse(cls, libraryUnit: Iir): + name = GetNameOfNode(libraryUnit) packageBody = cls(name) @@ -147,14 +168,14 @@ class PackageBody(VHDLModel_PackageBody, GHDLMixin): @export class Context(VHDLModel_Context, GHDLMixin): @classmethod - def parse(cls, libraryUnit): - name = NodeToName(libraryUnit) + def parse(cls, libraryUnit: Iir): + name = GetNameOfNode(libraryUnit) return cls(name) @export class Configuration(VHDLModel_Configuration, GHDLMixin): @classmethod - def parse(cls, libraryUnit): - name = NodeToName(libraryUnit) + def parse(cls, libraryUnit: Iir): + name = GetNameOfNode(libraryUnit) return cls(name) diff --git a/pyGHDL/dom/Expression.py b/pyGHDL/dom/Expression.py index fec347b57..b129e1ce5 100644 --- a/pyGHDL/dom/Expression.py +++ b/pyGHDL/dom/Expression.py @@ -32,19 +32,6 @@ # ============================================================================ from typing import List -from pyGHDL.dom.Aggregates import ( - OthersAggregateElement, - SimpleAggregateElement, - RangedAggregateElement, - IndexedAggregateElement, - NamedAggregateElement, -) -from pyGHDL.dom.Symbol import EnumerationLiteralSymbol -from pyGHDL.libghdl import utils - -from pyGHDL.dom.Common import DOMException -from pyGHDL.dom._Utils import GetIirKindOfNode -from pyGHDL.libghdl.vhdl import nodes from pydecor import export from pyVHDLModel.VHDLModel import ( @@ -52,7 +39,7 @@ from pyVHDLModel.VHDLModel import ( IdentityExpression as VHDLModel_IdentityExpression, NegationExpression as VHDLModel_NegationExpression, AbsoluteExpression as VHDLModel_AbsoluteExpression, - ParenthesisExpression as VHDLModel_ParenthesisExpression, + SubExpression as VHDLModel_ParenthesisExpression, TypeConversion as VHDLModel_TypeConversion, FunctionCall as VHDLModel_FunctionCall, QualifiedExpression as VHDLModel_QualifiedExpression, @@ -72,9 +59,10 @@ from pyVHDLModel.VHDLModel import ( XnorExpression as VHDLModel_XnorExpression, EqualExpression as VHDLModel_EqualExpression, UnequalExpression as VHDLModel_UnequalExpression, + LessThanExpression as VHDLModel_LessThanExpression, + LessEqualExpression as VHDLModel_LessEqualExpression, GreaterThanExpression as VHDLModel_GreaterThanExpression, GreaterEqualExpression as VHDLModel_GreaterEqualExpression, - LessThanExpression as VHDLModel_LessThanExpression, ShiftRightLogicExpression as VHDLModel_ShiftRightLogicExpression, ShiftLeftLogicExpression as VHDLModel_ShiftLeftLogicExpression, ShiftRightArithmeticExpression as VHDLModel_ShiftRightArithmeticExpression, @@ -84,8 +72,23 @@ from pyVHDLModel.VHDLModel import ( Aggregate as VHDLModel_Aggregate, Expression, AggregateElement, + SubTypeOrSymbol, +) + +from pyGHDL.libghdl import utils +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, + SimpleAggregateElement, + RangedAggregateElement, + IndexedAggregateElement, + NamedAggregateElement, ) + __all__ = [] @@ -165,13 +168,6 @@ class FunctionCall(VHDLModel_FunctionCall): @export -class QualifiedExpression(VHDLModel_QualifiedExpression): - def __init__(self, operand: Expression): - super().__init__() - self._operand = operand - - -@export class AdditionExpression(VHDLModel_AdditionExpression, _ParseBinaryExpression): def __init__(self, left: Expression, right: Expression): super().__init__() @@ -304,7 +300,7 @@ class UnequalExpression(VHDLModel_UnequalExpression, _ParseBinaryExpression): @export -class GreaterThanExpression(VHDLModel_GreaterThanExpression, _ParseBinaryExpression): +class LessThanExpression(VHDLModel_LessThanExpression, _ParseBinaryExpression): def __init__(self, left: Expression, right: Expression): super().__init__() self._leftOperand = left @@ -312,7 +308,7 @@ class GreaterThanExpression(VHDLModel_GreaterThanExpression, _ParseBinaryExpress @export -class GreaterEqualExpression(VHDLModel_GreaterEqualExpression, _ParseBinaryExpression): +class LessEqualExpression(VHDLModel_LessEqualExpression, _ParseBinaryExpression): def __init__(self, left: Expression, right: Expression): super().__init__() self._leftOperand = left @@ -320,7 +316,15 @@ class GreaterEqualExpression(VHDLModel_GreaterEqualExpression, _ParseBinaryExpre @export -class LessThanExpression(VHDLModel_LessThanExpression, _ParseBinaryExpression): +class GreaterThanExpression(VHDLModel_GreaterThanExpression, _ParseBinaryExpression): + def __init__(self, left: Expression, right: Expression): + super().__init__() + self._leftOperand = left + self._rightOperand = right + + +@export +class GreaterEqualExpression(VHDLModel_GreaterEqualExpression, _ParseBinaryExpression): def __init__(self, left: Expression, right: Expression): super().__init__() self._leftOperand = left @@ -384,6 +388,23 @@ class RotateLeftExpression(VHDLModel_RotateLeftExpression, _ParseBinaryExpressio @export +class QualifiedExpression(VHDLModel_QualifiedExpression): + def __init__(self, subType: SubTypeOrSymbol, operand: Expression): + super().__init__() + self._subtype = subType + self._operand = operand + + @classmethod + def parse(cls, node): + from pyGHDL.dom._Translate import GetExpressionFromNode, GetNameOfNode + + typeMarkName = GetNameOfNode(nodes.Get_Type_Mark(node)) + subType = SimpleSubTypeSymbol(typeMarkName) + operand = GetExpressionFromNode(nodes.Get_Expression(node)) + return cls(subType, operand) + + +@export class Aggregate(VHDLModel_Aggregate): def __init__(self, elements: List[AggregateElement]): super().__init__() @@ -391,31 +412,28 @@ class Aggregate(VHDLModel_Aggregate): @classmethod def parse(cls, node): - from pyGHDL.dom._Translate import GetExpressionFromNode + from pyGHDL.dom._Translate import GetExpressionFromNode, GetRangeFromNode choices = [] choicesChain = nodes.Get_Association_Choices_Chain(node) for item in utils.chain_iter(choicesChain): kind = GetIirKindOfNode(item) + value = GetExpressionFromNode(nodes.Get_Associated_Expr(item)) + if kind == nodes.Iir_Kind.Choice_By_None: - value = GetExpressionFromNode(nodes.Get_Associated_Expr(item)) choices.append(SimpleAggregateElement(value)) elif kind == nodes.Iir_Kind.Choice_By_Expression: index = GetExpressionFromNode(nodes.Get_Choice_Expression(item)) - value = GetExpressionFromNode(nodes.Get_Associated_Expr(item)) choices.append(IndexedAggregateElement(index, value)) elif kind == nodes.Iir_Kind.Choice_By_Range: - r = GetExpressionFromNode(nodes.Get_Choice_Range(item)) - value = GetExpressionFromNode(nodes.Get_Associated_Expr(item)) + r = GetRangeFromNode(nodes.Get_Choice_Range(item)) choices.append(RangedAggregateElement(r, value)) elif kind == nodes.Iir_Kind.Choice_By_Name: name = EnumerationLiteralSymbol(nodes.Get_Choice_Name(item)) - value = GetExpressionFromNode(nodes.Get_Associated_Expr(item)) choices.append(NamedAggregateElement(name, value)) elif kind == nodes.Iir_Kind.Choice_By_Others: - expression = None - choices.append(OthersAggregateElement(expression)) + choices.append(OthersAggregateElement(value)) else: raise DOMException( "Unknown choice kind '{kindName}'({kind}) in aggregate '{aggr}'.".format( diff --git a/pyGHDL/dom/InterfaceItem.py b/pyGHDL/dom/InterfaceItem.py index c2cd3a2c9..eac92c8a6 100644 --- a/pyGHDL/dom/InterfaceItem.py +++ b/pyGHDL/dom/InterfaceItem.py @@ -30,39 +30,41 @@ # # SPDX-License-Identifier: GPL-2.0-or-later # ============================================================================ -from pyGHDL.libghdl.vhdl.nodes import Null_Iir - -from pyGHDL.libghdl.vhdl import nodes from pydecor import export from pyVHDLModel.VHDLModel import ( GenericConstantInterfaceItem as VHDLModel_GenericConstantInterfaceItem, PortSignalInterfaceItem as VHDLModel_PortSignalInterfaceItem, + ParameterConstantInterfaceItem as VHDLModel_ParameterConstantInterfaceItem, + ParameterVariableInterfaceItem as VHDLModel_ParameterVariableInterfaceItem, + ParameterSignalInterfaceItem as VHDLModel_ParameterSignalInterfaceItem, Mode, SubTypeOrSymbol, Expression, ) -from pyGHDL.dom._Utils import NodeToName, GetModeOfNode +from pyGHDL.libghdl.vhdl import nodes +from pyGHDL.libghdl.vhdl.nodes import Null_Iir +from pyGHDL.dom._Utils import GetNameOfNode, GetModeOfNode from pyGHDL.dom._Translate import GetSubtypeIndicationFromNode, GetExpressionFromNode -from pyGHDL.dom.Common import GHDLMixin + __all__ = [] @export -class GenericConstantInterfaceItem(VHDLModel_GenericConstantInterfaceItem, GHDLMixin): +class GenericConstantInterfaceItem(VHDLModel_GenericConstantInterfaceItem): @classmethod def parse(cls, generic): - name = NodeToName(generic) + name = GetNameOfNode(generic) mode = GetModeOfNode(generic) subTypeIndication = GetSubtypeIndicationFromNode(generic, "generic", name) default = nodes.Get_Default_Value(generic) value = GetExpressionFromNode(default) if default else None - generic = cls(name, mode, subTypeIndication, value) + g = cls(name, mode, subTypeIndication, value) - return generic + return g def __init__( self, @@ -77,10 +79,10 @@ class GenericConstantInterfaceItem(VHDLModel_GenericConstantInterfaceItem, GHDLM @export -class PortSignalInterfaceItem(VHDLModel_PortSignalInterfaceItem, GHDLMixin): +class PortSignalInterfaceItem(VHDLModel_PortSignalInterfaceItem): @classmethod def parse(cls, port): - name = NodeToName(port) + name = GetNameOfNode(port) mode = GetModeOfNode(port) subTypeIndication = GetSubtypeIndicationFromNode(port, "port", name) @@ -89,9 +91,96 @@ class PortSignalInterfaceItem(VHDLModel_PortSignalInterfaceItem, GHDLMixin): GetExpressionFromNode(defaultValue) if defaultValue != Null_Iir else None ) - port = cls(name, mode, subTypeIndication, value) + p = cls(name, mode, subTypeIndication, value) + + return p + + def __init__( + self, + name: str, + mode: Mode, + subType: SubTypeOrSymbol, + defaultExpression: Expression = None, + ): + super().__init__(name=name, mode=mode) + 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) + + defaultValue = nodes.Get_Default_Value(parameter) + value = ( + GetExpressionFromNode(defaultValue) if defaultValue != Null_Iir else None + ) + + param = cls(name, mode, subTypeIndication, value) + + return param + + def __init__( + self, + name: str, + mode: Mode, + subType: SubTypeOrSymbol, + defaultExpression: Expression = None, + ): + super().__init__(name=name, mode=mode) + 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) + + defaultValue = nodes.Get_Default_Value(parameter) + value = ( + GetExpressionFromNode(defaultValue) if defaultValue != Null_Iir else None + ) + + param = cls(name, mode, subTypeIndication, value) + + return param + + def __init__( + self, + name: str, + mode: Mode, + subType: SubTypeOrSymbol, + defaultExpression: Expression = None, + ): + super().__init__(name=name, mode=mode) + 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) + + defaultValue = nodes.Get_Default_Value(parameter) + value = ( + GetExpressionFromNode(defaultValue) if defaultValue != Null_Iir else None + ) + + param = cls(name, mode, subTypeIndication, value) - return port + return param def __init__( self, diff --git a/pyGHDL/dom/Literal.py b/pyGHDL/dom/Literal.py index 7c722583b..209712ba3 100644 --- a/pyGHDL/dom/Literal.py +++ b/pyGHDL/dom/Literal.py @@ -30,16 +30,19 @@ # # SPDX-License-Identifier: GPL-2.0-or-later # ============================================================================ -from pyGHDL.libghdl import name_table - -from pyGHDL.libghdl.vhdl import nodes from pydecor import export from pyVHDLModel.VHDLModel import ( IntegerLiteral as VHDLModel_IntegerLiteral, FloatingPointLiteral as VHDLModel_FloatingPointLiteral, + PhysicalIntegerLiteral as VHDLModel_PhysicalIntegerLiteral, + PhysicalFloatingLiteral as VHDLModel_PhysicalFloatingLiteral, CharacterLiteral as VHDLModel_CharacterLiteral, + StringLiteral as VHDLModel_StringLiteral, ) +from pyGHDL.libghdl import name_table +from pyGHDL.libghdl.vhdl import nodes +from pyGHDL.dom._Utils import GetNameOfNode __all__ = [] @@ -61,9 +64,40 @@ class FloatingPointLiteral(VHDLModel_FloatingPointLiteral): @export +class PhysicalIntegerLiteral(VHDLModel_PhysicalIntegerLiteral): + @classmethod + def parse(cls, node): + value = nodes.Get_Value(node) + unit = nodes.Get_Unit_Name(node) + unitName = GetNameOfNode(unit) + + return cls(value, unitName) + + +@export +class PhysicalFloatingLiteral(VHDLModel_PhysicalFloatingLiteral): + @classmethod + def parse(cls, node): + value = nodes.Get_Fp_Value(node) + unit = nodes.Get_Unit_Name(node) + unitName = GetNameOfNode(unit) + + return cls(value, unitName) + + +@export class CharacterLiteral(VHDLModel_CharacterLiteral): @classmethod def parse(cls, node): identifier = nodes.Get_Identifier(node) value = name_table.Get_Character(identifier) return cls(value) + + +@export +class StringLiteral(VHDLModel_StringLiteral): + @classmethod + def parse(cls, node): + stringID = nodes.Get_String8_Id(node) + value = name_table.Get_Name_Ptr(stringID) + return cls(value) diff --git a/pyGHDL/dom/Misc.py b/pyGHDL/dom/Misc.py index 7bee2ec7b..8bea6cf61 100644 --- a/pyGHDL/dom/Misc.py +++ b/pyGHDL/dom/Misc.py @@ -35,133 +35,41 @@ .. todo:: Add a module documentation. """ -from pathlib import Path -from typing import Any - from pydecor import export -from pyVHDLModel.VHDLModel import Design as VHDLModel_Design -from pyVHDLModel.VHDLModel import Library as VHDLModel_Library -from pyVHDLModel.VHDLModel import Document as VHDLModel_Document - -import pyGHDL.libghdl as libghdl -from pyGHDL.libghdl import ( - name_table, - files_map, - errorout_memory, - LibGHDLException, - utils, +from pyVHDLModel.VHDLModel import ( + Alias as VHDLModel_Alias, ) -from pyGHDL.libghdl.vhdl import nodes, sem_lib, parse -from pyGHDL.dom._Utils import GetIirKindOfNode -from pyGHDL.dom.Common import DOMException, GHDLMixin -from pyGHDL.dom.DesignUnit import ( - Entity, - Architecture, - Package, - PackageBody, - Context, - Configuration, -) __all__ = [] @export -class Design(VHDLModel_Design): - def __init__(self): - super().__init__() - - self.__ghdl_init() - - def __ghdl_init(self): - """Initialization: set options and then load libraries""" - # Initialize libghdl - libghdl.finalize() - libghdl.initialize() - - # Collect error messages in memory - errorout_memory.Install_Handler() +class Position: + _filename: str + _line: int + _column: int - libghdl.set_option("--std=08") + def __init__(self, filename: str, line: int, column: int): + self._filename = filename + self._line = line + self._column = column - parse.Flag_Parse_Parenthesis.value = True + @property + def Filename(self): + return self._filename - # Finish initialization. This will load the standard package. - if libghdl.analyze_init_status() != 0: - raise LibGHDLException("Error initializing 'libghdl'.") + @property + def Line(self): + return self._line - -@export -class Library(VHDLModel_Library): - pass + @property + def Column(self): + return self._column @export -class Document(VHDLModel_Document, GHDLMixin): - __ghdlFileID: Any - __ghdlSourceFileEntry: Any - __ghdlFile: Any - - def __init__(self, path: Path = None, dontParse: bool = False): - super().__init__(path) - GHDLMixin.__init__(self) - - self.__ghdl_init() - if dontParse == False: - self.parse() - - def __ghdl_init(self): - # Read input file - self.__ghdlFileID = name_table.Get_Identifier(str(self.Path)) - self.__ghdlSourceFileEntry = files_map.Read_Source_File( - name_table.Null_Identifier, self.__ghdlFileID - ) - if self.__ghdlSourceFileEntry == files_map.No_Source_File_Entry: - raise LibGHDLException("Cannot load file '{!s}'".format(self.Path)) - - self.CheckForErrors() - - # Parse input file - self.__ghdlFile = sem_lib.Load_File(self.__ghdlSourceFileEntry) - - self.CheckForErrors() - - def parse(self): - firstUnit = nodes.Get_First_Design_Unit(self.__ghdlFile) - - for unit in utils.chain_iter(firstUnit): - libraryUnit = nodes.Get_Library_Unit(unit) - nodeKind = GetIirKindOfNode(libraryUnit) - - if nodeKind == nodes.Iir_Kind.Entity_Declaration: - entity = Entity.parse(libraryUnit) - self.Entities.append(entity) - - elif nodeKind == nodes.Iir_Kind.Architecture_Body: - architecture = Architecture.parse(libraryUnit) - self.Architectures.append(architecture) - - elif nodeKind == nodes.Iir_Kind.Package_Declaration: - package = Package.parse(libraryUnit) - self.Packages.append(package) - - elif nodeKind == nodes.Iir_Kind.Package_Body: - packageBody = PackageBody.parse(libraryUnit) - self.PackageBodies.append(packageBody) - - elif nodeKind == nodes.Iir_Kind.Context_Declaration: - context = Context.parse(libraryUnit) - self.Contexts.append(context) - - elif nodeKind == nodes.Iir_Kind.Configuration_Declaration: - configuration = Configuration.parse(libraryUnit) - self.Configurations.append(configuration) - - else: - raise DOMException( - "Unknown design unit kind '{kindName}'({kind}).".format( - kindName=nodeKind.name, kind=nodeKind - ) - ) +class Alias(VHDLModel_Alias): + def __init__(self, aliasName: str): + super().__init__(aliasName) diff --git a/pyGHDL/dom/NonStandard.py b/pyGHDL/dom/NonStandard.py new file mode 100644 index 000000000..9010e392b --- /dev/null +++ b/pyGHDL/dom/NonStandard.py @@ -0,0 +1,172 @@ +# ============================================================================= +# ____ _ _ ____ _ _ +# _ __ _ _ / ___| | | | _ \| | __| | ___ _ __ ___ +# | '_ \| | | | | _| |_| | | | | | / _` |/ _ \| '_ ` _ \ +# | |_) | |_| | |_| | _ | |_| | |___ | (_| | (_) | | | | | | +# | .__/ \__, |\____|_| |_|____/|_____(_)__,_|\___/|_| |_| |_| +# |_| |___/ +# ============================================================================= +# Authors: +# Patrick Lehmann +# +# Package module: DOM: Elements not covered by the VHDL standard. +# +# 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 pathlib import Path +from typing import Any + +from pydecor import export + +from pyVHDLModel.VHDLModel import ( + Design as VHDLModel_Design, + Library as VHDLModel_Library, + Document as VHDLModel_Document, +) + +from pyGHDL.libghdl import ( + initialize as libghdl_initialize, + finalize as libghdl_finalize, + set_option as libghdl_set_option, + analyze_init_status as libghdl_analyze_init_status, + name_table, + files_map, + errorout_memory, + LibGHDLException, + utils, +) +from pyGHDL.libghdl.vhdl import nodes, sem_lib, parse +from pyGHDL.dom._Utils import GetIirKindOfNode +from pyGHDL.dom.Common import DOMException, GHDLMixin +from pyGHDL.dom.DesignUnit import ( + Entity, + Architecture, + Package, + PackageBody, + Context, + Configuration, +) + +__all__ = [] + + +@export +class Design(VHDLModel_Design): + def __init__(self): + super().__init__() + + self.__ghdl_init() + + def __ghdl_init(self): + """Initialization: set options and then load libraries.""" + + # Initialize libghdl + libghdl_finalize() + libghdl_initialize() + + # Collect error messages in memory + errorout_memory.Install_Handler() + + libghdl_set_option("--std=08") + + parse.Flag_Parse_Parenthesis.value = True + + # Finish initialization. This will load the standard package. + if libghdl_analyze_init_status() != 0: + raise LibGHDLException("Error initializing 'libghdl'.") + + +@export +class Library(VHDLModel_Library): + pass + + +@export +class Document(VHDLModel_Document, GHDLMixin): + __ghdlFileID: Any + __ghdlSourceFileEntry: Any + __ghdlFile: Any + + def __init__(self, path: Path = None, dontParse: bool = False): + super().__init__(path) + GHDLMixin.__init__(self) + + self.__ghdl_init() + if dontParse == False: + self.parse() + + def __ghdl_init(self): + # Read input file + self.__ghdlFileID = name_table.Get_Identifier(str(self.Path)) + self.__ghdlSourceFileEntry = files_map.Read_Source_File( + name_table.Null_Identifier, self.__ghdlFileID + ) + if self.__ghdlSourceFileEntry == files_map.No_Source_File_Entry: + raise LibGHDLException("Cannot load file '{!s}'".format(self.Path)) + + self.CheckForErrors() + + # Parse input file + self.__ghdlFile = sem_lib.Load_File(self.__ghdlSourceFileEntry) + + self.CheckForErrors() + + def parse(self): + firstUnit = nodes.Get_First_Design_Unit(self.__ghdlFile) + + for unit in utils.chain_iter(firstUnit): + libraryUnit = nodes.Get_Library_Unit(unit) + nodeKind = GetIirKindOfNode(libraryUnit) + + if nodeKind == nodes.Iir_Kind.Entity_Declaration: + entity = Entity.parse(libraryUnit) + self.Entities.append(entity) + + elif nodeKind == nodes.Iir_Kind.Architecture_Body: + architecture = Architecture.parse(libraryUnit) + self.Architectures.append(architecture) + + elif nodeKind == nodes.Iir_Kind.Package_Declaration: + package = Package.parse(libraryUnit) + self.Packages.append(package) + + elif nodeKind == nodes.Iir_Kind.Package_Body: + packageBody = PackageBody.parse(libraryUnit) + self.PackageBodies.append(packageBody) + + elif nodeKind == nodes.Iir_Kind.Context_Declaration: + context = Context.parse(libraryUnit) + self.Contexts.append(context) + + elif nodeKind == nodes.Iir_Kind.Configuration_Declaration: + configuration = Configuration.parse(libraryUnit) + self.Configurations.append(configuration) + + else: + raise DOMException( + "Unknown design unit kind '{kindName}'({kind}).".format( + kindName=nodeKind.name, kind=nodeKind + ) + ) diff --git a/pyGHDL/dom/Object.py b/pyGHDL/dom/Object.py index bd37455ea..1f1f8f6d9 100644 --- a/pyGHDL/dom/Object.py +++ b/pyGHDL/dom/Object.py @@ -34,7 +34,7 @@ from pyGHDL.libghdl.vhdl import nodes from pydecor import export from pyGHDL.dom._Translate import GetSubtypeIndicationFromNode, GetExpressionFromNode -from pyGHDL.dom._Utils import NodeToName +from pyGHDL.dom._Utils import GetNameOfNode from pyVHDLModel.VHDLModel import ( Constant as VHDLModel_Constant, Variable as VHDLModel_Variable, @@ -59,7 +59,7 @@ class Constant(VHDLModel_Constant): @classmethod def parse(cls, node): - name = NodeToName(node) + name = GetNameOfNode(node) subTypeIndication = GetSubtypeIndicationFromNode(node, "constant", name) defaultExpression = GetExpressionFromNode(nodes.Get_Default_Value(node)) @@ -81,7 +81,7 @@ class Variable(VHDLModel_Variable): @classmethod def parse(cls, node): - name = NodeToName(node) + name = GetNameOfNode(node) subTypeIndication = GetSubtypeIndicationFromNode(node, "variable", name) defaultExpression = GetExpressionFromNode(nodes.Get_Default_Value(node)) @@ -103,7 +103,7 @@ class Signal(VHDLModel_Signal): @classmethod def parse(cls, node): - name = NodeToName(node) + name = GetNameOfNode(node) subTypeIndication = GetSubtypeIndicationFromNode(node, "signal", name) default = nodes.Get_Default_Value(node) defaultExpression = GetExpressionFromNode(default) if default else None diff --git a/pyGHDL/dom/Subprogram.py b/pyGHDL/dom/Subprogram.py new file mode 100644 index 000000000..b3c47bfe5 --- /dev/null +++ b/pyGHDL/dom/Subprogram.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 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, + SubTypeOrSymbol, +) +from pyGHDL.libghdl._types import Iir + + +@export +class Function(VHDLModel_Function): + def __init__(self, functionName: str, returnType: SubTypeOrSymbol): + super().__init__(functionName) + self._returnType = returnType + + @classmethod + def parse(cls, node: Iir): + from pyGHDL.dom._Translate import ( + GetGenericsFromChainedNodes, + GetParameterFromChainedNodes, + ) + + functionName = GetNameOfNode(node) + returnType = nodes.Get_Return_Type_Mark(node) + returnTypeName = GetNameOfNode(returnType) + + returnTypeSymbol = SimpleSubTypeSymbol(returnTypeName) + function = cls(functionName, returnTypeSymbol) + + for generic in GetGenericsFromChainedNodes(nodes.Get_Generic_Chain(node)): + function.GenericItems.append(generic) + for port in GetParameterFromChainedNodes( + nodes.Get_Interface_Declaration_Chain(node) + ): + function.ParameterItems.append(port) + + return function + + +@export +class Procedure(VHDLModel_Procedure): + def __init__(self, procedureName: str): + super().__init__(procedureName) + + @classmethod + def parse(cls, node: Iir): + from pyGHDL.dom._Translate import ( + GetGenericsFromChainedNodes, + GetParameterFromChainedNodes, + ) + + procedureName = GetNameOfNode(node) + + procedure = cls(procedureName) + + for generic in GetGenericsFromChainedNodes(nodes.Get_Generic_Chain(node)): + procedure.GenericItems.append(generic) + for port in GetParameterFromChainedNodes( + nodes.Get_Interface_Declaration_Chain(node) + ): + procedure.ParameterItems.append(port) + + return procedure diff --git a/pyGHDL/dom/Symbol.py b/pyGHDL/dom/Symbol.py index 020f9fbc7..1865e4481 100644 --- a/pyGHDL/dom/Symbol.py +++ b/pyGHDL/dom/Symbol.py @@ -30,20 +30,24 @@ # # SPDX-License-Identifier: GPL-2.0-or-later # ============================================================================ -from pydecor import export - from typing import List +from pydecor import export -from pyGHDL.dom._Utils import NodeToName from pyVHDLModel.VHDLModel import ( EntitySymbol as VHDLModel_EntitySymbol, SimpleSubTypeSymbol as VHDLModel_SimpleSubTypeSymbol, ConstrainedSubTypeSymbol as VHDLModel_ConstrainedSubTypeSymbol, EnumerationLiteralSymbol as VHDLModel_EnumerationLiteralSymbol, - SimpleObjectSymbol as VHDLModel_SimpleObjectSymbol, + SimpleObjectOrFunctionCallSymbol as VHDLModel_SimpleObjectOrFunctionCallSymbol, + IndexedObjectOrFunctionCallSymbol as VHDLModel_IndexedObjectOrFunctionCallSymbol, Constraint, ) +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__ = [] @@ -80,8 +84,39 @@ class ConstrainedSubTypeSymbol(VHDLModel_ConstrainedSubTypeSymbol): @export -class SimpleObjectSymbol(VHDLModel_SimpleObjectSymbol): +class SimpleObjectOrFunctionCallSymbol(VHDLModel_SimpleObjectOrFunctionCallSymbol): @classmethod def parse(cls, node): - name = NodeToName(node) + name = GetNameOfNode(node) return cls(name) + + +@export +class IndexedObjectOrFunctionCallSymbol(VHDLModel_IndexedObjectOrFunctionCallSymbol): + def __init__(self, name: str, associations: List): + super().__init__(objectName=name) + + @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) + + 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 cls(name, associations) diff --git a/pyGHDL/dom/Type.py b/pyGHDL/dom/Type.py new file mode 100644 index 000000000..c276387c7 --- /dev/null +++ b/pyGHDL/dom/Type.py @@ -0,0 +1,53 @@ +# ============================================================================= +# ____ _ _ ____ _ _ +# _ __ _ _ / ___| | | | _ \| | __| | ___ _ __ ___ +# | '_ \| | | | | _| |_| | | | | | / _` |/ _ \| '_ ` _ \ +# | |_) | |_| | |_| | _ | |_| | |___ | (_| | (_) | | | | | | +# | .__/ \__, |\____|_| |_|____/|_____(_)__,_|\___/|_| |_| |_| +# |_| |___/ +# ============================================================================= +# 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 ( + IntegerType as VHDLModel_IntegerType, + SubType as VHDLModel_SubType, + Expression, +) + + +@export +class IntegerType(VHDLModel_IntegerType): + def __init__(self, typeName: str, leftBound: Expression, rightBound: Expression): + super().__init__(typeName) + self._leftBound = leftBound + self._rightBound = rightBound + + +@export +class SubType(VHDLModel_SubType): + def __init__(self, subtypeName: str): + super().__init__(subtypeName) diff --git a/pyGHDL/dom/_Translate.py b/pyGHDL/dom/_Translate.py index 24f056f33..2b2a44e60 100644 --- a/pyGHDL/dom/_Translate.py +++ b/pyGHDL/dom/_Translate.py @@ -33,20 +33,36 @@ from typing import List from pydecor import export -from pyVHDLModel.VHDLModel import Constraint, Direction, Expression, SubTypeOrSymbol + +from pyVHDLModel.VHDLModel import ( + Constraint, + Direction, + Expression, + SubTypeOrSymbol, + BaseType, +) from pyGHDL.libghdl import utils -from pyGHDL.libghdl.utils import flist_iter +from pyGHDL.libghdl._types import Iir from pyGHDL.libghdl.vhdl import nodes -from pyGHDL.dom._Utils import NodeToName, GetIirKindOfNode +from pyGHDL.dom._Utils import GetNameOfNode, GetIirKindOfNode, GetPositionOfNode from pyGHDL.dom.Common import DOMException -from pyGHDL.dom.Range import Range, RangeExpression from pyGHDL.dom.Symbol import ( - SimpleObjectSymbol, + SimpleObjectOrFunctionCallSymbol, SimpleSubTypeSymbol, ConstrainedSubTypeSymbol, + IndexedObjectOrFunctionCallSymbol, +) +from pyGHDL.dom.Type import IntegerType, SubType +from pyGHDL.dom.Range import Range, RangeExpression +from pyGHDL.dom.Literal import ( + IntegerLiteral, + CharacterLiteral, + FloatingPointLiteral, + StringLiteral, + PhysicalIntegerLiteral, + PhysicalFloatingLiteral, ) -from pyGHDL.dom.Literal import IntegerLiteral, CharacterLiteral, FloatingPointLiteral from pyGHDL.dom.Expression import ( SubtractionExpression, AdditionExpression, @@ -57,25 +73,50 @@ from pyGHDL.dom.Expression import ( Aggregate, NegationExpression, ParenthesisExpression, + ConcatenationExpression, + QualifiedExpression, + ModuloExpression, + RemainderExpression, + AndExpression, + NandExpression, + OrExpression, + NorExpression, + XorExpression, + XnorExpression, + EqualExpression, + UnequalExpression, + LessThanExpression, + GreaterThanExpression, + GreaterEqualExpression, + LessEqualExpression, + ShiftLeftLogicExpression, + ShiftRightLogicExpression, + ShiftLeftArithmeticExpression, + ShiftRightArithmeticExpression, + RotateLeftExpression, + RotateRightExpression, ) +from pyGHDL.dom.Subprogram import Function, Procedure +from pyGHDL.dom.Misc import Alias + __all__ = [] @export -def GetSubtypeIndicationFromNode(node, entity: str, name: str) -> SubTypeOrSymbol: +def GetSubtypeIndicationFromNode(node: Iir, entity: str, name: str) -> SubTypeOrSymbol: subTypeIndication = nodes.Get_Subtype_Indication(node) if subTypeIndication is nodes.Null_Iir: return None subTypeKind = GetIirKindOfNode(subTypeIndication) if subTypeKind == nodes.Iir_Kind.Simple_Name: - subTypeName = NodeToName(subTypeIndication) + subTypeName = GetNameOfNode(subTypeIndication) subType = SimpleSubTypeSymbol(subTypeName) elif subTypeKind == nodes.Iir_Kind.Array_Subtype_Definition: typeMark = nodes.Get_Subtype_Type_Mark(subTypeIndication) - typeMarkName = NodeToName(typeMark) + typeMarkName = GetNameOfNode(typeMark) constraints = GetArrayConstraintsFromSubtypeIndication(subTypeIndication) subType = ConstrainedSubTypeSymbol(typeMarkName, constraints) @@ -86,9 +127,16 @@ def GetSubtypeIndicationFromNode(node, entity: str, name: str) -> SubTypeOrSymbo ) ) else: + position = GetPositionOfNode(node) raise DOMException( - "Unknown subtype kind '{kind}' of subtype indication '{indication}' while parsing {entity} '{name}'.".format( - kind=subTypeKind, indication=subTypeIndication, entity=entity, name=name + "Unknown subtype kind '{kind}' of subtype indication '{indication}' while parsing {entity} '{name}' at {file}:{line}:{column}.".format( + kind=subTypeKind, + indication=subTypeIndication, + entity=entity, + name=name, + file=position.Filename, + line=position.Line, + column=position.Column, ) ) @@ -96,64 +144,124 @@ def GetSubtypeIndicationFromNode(node, entity: str, name: str) -> SubTypeOrSymbo @export -def GetArrayConstraintsFromSubtypeIndication(subTypeIndication) -> List[Constraint]: +def GetArrayConstraintsFromSubtypeIndication( + subTypeIndication: Iir, +) -> List[Constraint]: constraints = [] - for constraint in flist_iter(nodes.Get_Index_Constraint_List(subTypeIndication)): + for constraint in utils.flist_iter( + nodes.Get_Index_Constraint_List(subTypeIndication) + ): constraintKind = GetIirKindOfNode(constraint) if constraintKind == nodes.Iir_Kind.Range_Expression: - direction = nodes.Get_Direction(constraint) - leftBound = nodes.Get_Left_Limit_Expr(constraint) - rightBound = nodes.Get_Right_Limit_Expr(constraint) - - r = Range( - GetExpressionFromNode(leftBound), - GetExpressionFromNode(rightBound), - Direction.DownTo if direction else Direction.To, - ) - constraints.append(RangeExpression(r)) + constraints.append(RangeExpression(GetRangeFromNode(constraint))) elif constraintKind == nodes.Iir_Kind.Attribute_Name: raise DOMException("[NOT IMPLEMENTED] Attribute name as range.") elif constraintKind == nodes.Iir_Kind.Simple_Name: raise DOMException("[NOT IMPLEMENTED] Subtype as range.") else: + position = GetPositionOfNode(constraint) raise DOMException( - "Unknown constraint kind '{kind}' for constraint '{constraint}' in subtype indication '{indication}'.".format( + "Unknown constraint kind '{kind}' for constraint '{constraint}' in subtype indication '{indication}' at {file}:{line}:{column}.".format( kind=constraintKind, constraint=constraint, indication=subTypeIndication, + file=position.Filename, + line=position.Line, + column=position.Column, ) ) return constraints +@export +def GetTypeFromNode(node: Iir) -> BaseType: + typeName = GetNameOfNode(node) + leftBound = IntegerLiteral(0) + rightBound = IntegerLiteral(15) + + return IntegerType(typeName, leftBound, rightBound) + + +@export +def GetSubTypeFromNode(node: Iir) -> BaseType: + subTypeName = GetNameOfNode(node) + + return SubType(subTypeName) + + +@export +def GetRangeFromNode(node: Iir) -> Range: + direction = nodes.Get_Direction(node) + leftBound = nodes.Get_Left_Limit_Expr(node) + rightBound = nodes.Get_Right_Limit_Expr(node) + + return Range( + GetExpressionFromNode(leftBound), + GetExpressionFromNode(rightBound), + Direction.DownTo if direction else Direction.To, + ) + + __EXPRESSION_TRANSLATION = { - nodes.Iir_Kind.Simple_Name: SimpleObjectSymbol, + nodes.Iir_Kind.Simple_Name: SimpleObjectOrFunctionCallSymbol, + nodes.Iir_Kind.Parenthesis_Name: IndexedObjectOrFunctionCallSymbol, nodes.Iir_Kind.Integer_Literal: IntegerLiteral, nodes.Iir_Kind.Floating_Point_Literal: FloatingPointLiteral, + nodes.Iir_Kind.Physical_Int_Literal: PhysicalIntegerLiteral, + nodes.Iir_Kind.Physical_Fp_Literal: PhysicalFloatingLiteral, nodes.Iir_Kind.Character_Literal: CharacterLiteral, + nodes.Iir_Kind.String_Literal8: StringLiteral, nodes.Iir_Kind.Negation_Operator: NegationExpression, nodes.Iir_Kind.Addition_Operator: AdditionExpression, + nodes.Iir_Kind.Concatenation_Operator: ConcatenationExpression, nodes.Iir_Kind.Not_Operator: InverseExpression, nodes.Iir_Kind.Parenthesis_Expression: ParenthesisExpression, nodes.Iir_Kind.Substraction_Operator: SubtractionExpression, nodes.Iir_Kind.Multiplication_Operator: MultiplyExpression, nodes.Iir_Kind.Division_Operator: DivisionExpression, + nodes.Iir_Kind.Modulus_Operator: ModuloExpression, + nodes.Iir_Kind.Remainder_Operator: RemainderExpression, nodes.Iir_Kind.Exponentiation_Operator: ExponentiationExpression, + nodes.Iir_Kind.And_Operator: AndExpression, + nodes.Iir_Kind.Nand_Operator: NandExpression, + nodes.Iir_Kind.Or_Operator: OrExpression, + nodes.Iir_Kind.Nor_Operator: NorExpression, + nodes.Iir_Kind.Xor_Operator: XorExpression, + nodes.Iir_Kind.Xnor_Operator: XnorExpression, + nodes.Iir_Kind.Equality_Operator: EqualExpression, + nodes.Iir_Kind.Inequality_Operator: UnequalExpression, + nodes.Iir_Kind.Less_Than_Operator: LessThanExpression, + nodes.Iir_Kind.Less_Than_Or_Equal_Operator: LessEqualExpression, + nodes.Iir_Kind.Greater_Than_Operator: GreaterThanExpression, + nodes.Iir_Kind.Greater_Than_Or_Equal_Operator: GreaterEqualExpression, + nodes.Iir_Kind.Sll_Operator: ShiftLeftLogicExpression, + nodes.Iir_Kind.Srl_Operator: ShiftRightLogicExpression, + nodes.Iir_Kind.Sla_Operator: ShiftLeftArithmeticExpression, + nodes.Iir_Kind.Sra_Operator: ShiftRightArithmeticExpression, + nodes.Iir_Kind.Rol_Operator: RotateLeftExpression, + nodes.Iir_Kind.Ror_Operator: RotateRightExpression, + nodes.Iir_Kind.Qualified_Expression: QualifiedExpression, nodes.Iir_Kind.Aggregate: Aggregate, } @export -def GetExpressionFromNode(node) -> Expression: +def GetExpressionFromNode(node: Iir) -> Expression: kind = GetIirKindOfNode(node) try: cls = __EXPRESSION_TRANSLATION[kind] except KeyError: + position = GetPositionOfNode(node) raise DOMException( - "Unknown expression kind '{kindName}'({kind}) in expression '{expr}'.".format( - kind=kind, kindName=kind.name, expr=node + "Unknown expression kind '{kindName}'({kind}) in expression '{expr}' at {file}:{line}:{column}.".format( + kind=kind, + kindName=kind.name, + expr=node, + file=position.Filename, + line=position.Line, + column=position.Column, ) ) @@ -162,7 +270,7 @@ def GetExpressionFromNode(node) -> Expression: # FIXME: rewrite to generator @export -def GetGenericsFromChainedNodes(nodeChain): +def GetGenericsFromChainedNodes(nodeChain: Iir): result = [] for generic in utils.chain_iter(nodeChain): kind = GetIirKindOfNode(generic) @@ -173,9 +281,15 @@ def GetGenericsFromChainedNodes(nodeChain): result.append(genericConstant) else: + position = GetPositionOfNode(generic) raise DOMException( - "Unknown generic kind '{kindName}'({kind}) in generic '{generic}'.".format( - kind=kind, kindName=kind.name, generic=generic + "Unknown generic kind '{kindName}'({kind}) in generic '{generic}' at {file}:{line}:{column}.".format( + kind=kind, + kindName=kind.name, + generic=generic, + file=position.Filename, + line=position.Line, + column=position.Column, ) ) @@ -184,7 +298,7 @@ def GetGenericsFromChainedNodes(nodeChain): # FIXME: rewrite to generator @export -def GetPortsFromChainedNodes(nodeChain): +def GetPortsFromChainedNodes(nodeChain: Iir): result = [] for port in utils.chain_iter(nodeChain): kind = GetIirKindOfNode(port) @@ -195,16 +309,56 @@ def GetPortsFromChainedNodes(nodeChain): result.append(portSignal) else: + position = GetPositionOfNode(port) raise DOMException( - "Unknown port kind '{kindName}'({kind}) in port '{port}'.".format( - kind=kind, kindName=kind.name, port=port + "Unknown port kind '{kindName}'({kind}) in port '{port}' at {file}:{line}:{column}.".format( + kind=kind, + kindName=kind.name, + port=port, + file=position.Filename, + line=position.Line, + column=position.Column, ) ) return result -def GetDeclaredItemsFromChainedNodes(nodeChain, entity: str, name: str): +# FIXME: rewrite to generator +@export +def GetParameterFromChainedNodes(nodeChain: Iir): + result = [] + for parameter in utils.chain_iter(nodeChain): + kind = GetIirKindOfNode(parameter) + if kind == nodes.Iir_Kind.Interface_Constant_Declaration: + from pyGHDL.dom.InterfaceItem import ParameterConstantInterfaceItem + + result.append(ParameterConstantInterfaceItem.parse(parameter)) + elif kind == nodes.Iir_Kind.Interface_Variable_Declaration: + from pyGHDL.dom.InterfaceItem import ParameterVariableInterfaceItem + + result.append(ParameterVariableInterfaceItem.parse(parameter)) + elif kind == nodes.Iir_Kind.Interface_Signal_Declaration: + from pyGHDL.dom.InterfaceItem import ParameterSignalInterfaceItem + + result.append(ParameterSignalInterfaceItem.parse(parameter)) + else: + position = GetPositionOfNode(parameter) + raise DOMException( + "Unknown parameter kind '{kindName}'({kind}) in parameter '{param}' at {file}:{line}:{column}.".format( + kind=kind, + kindName=kind.name, + param=parameter, + file=position.Filename, + line=position.Line, + column=position.Column, + ) + ) + + return result + + +def GetDeclaredItemsFromChainedNodes(nodeChain: Iir, entity: str, name: str): result = [] for item in utils.chain_iter(nodeChain): kind = GetIirKindOfNode(item) @@ -216,26 +370,46 @@ def GetDeclaredItemsFromChainedNodes(nodeChain, entity: str, name: str): from pyGHDL.dom.Object import Signal result.append(Signal.parse(item)) + elif kind == nodes.Iir_Kind.Type_Declaration: + result.append(GetTypeFromNode(item)) elif kind == nodes.Iir_Kind.Anonymous_Type_Declaration: - typeName = NodeToName(item) - print("found type '{name}'".format(name=typeName)) + result.append(GetTypeFromNode(item)) elif kind == nodes.Iir_Kind.Subtype_Declaration: - subTypeName = NodeToName(item) - print("found subtype '{name}'".format(name=subTypeName)) + result.append(GetSubTypeFromNode(item)) elif kind == nodes.Iir_Kind.Function_Declaration: - functionName = NodeToName(item) - print("found function '{name}'".format(name=functionName)) + result.append(Function.parse(item)) elif kind == nodes.Iir_Kind.Function_Body: - # functionName = NodeToName(item) + # procedureName = NodeToName(item) print("found function body '{name}'".format(name="????")) + elif kind == nodes.Iir_Kind.Procedure_Declaration: + result.append(Procedure.parse(item)) + elif kind == nodes.Iir_Kind.Procedure_Body: + # procedureName = NodeToName(item) + print("found procedure body '{name}'".format(name="????")) elif kind == nodes.Iir_Kind.Object_Alias_Declaration: - aliasName = NodeToName(item) - print("found alias '{name}'".format(name=aliasName)) + result.append(GetAliasFromNode(item)) + elif kind == nodes.Iir_Kind.Component_Declaration: + from pyGHDL.dom.DesignUnit import Component + + result.append(Component.parse(item)) else: + position = GetPositionOfNode(item) raise DOMException( - "Unknown declared item kind '{kindName}'({kind}) in {entity} '{name}'.".format( - kind=kind, kindName=kind.name, entity=entity, name=name + "Unknown declared item kind '{kindName}'({kind}) in {entity} '{name}' at {file}:{line}:{column}.".format( + kind=kind, + kindName=kind.name, + entity=entity, + name=name, + file=position.Filename, + line=position.Line, + column=position.Column, ) ) return result + + +def GetAliasFromNode(node: Iir): + aliasName = GetNameOfNode(node) + + return Alias(aliasName) diff --git a/pyGHDL/dom/_Utils.py b/pyGHDL/dom/_Utils.py index dbbb69e81..38a85c0c3 100644 --- a/pyGHDL/dom/_Utils.py +++ b/pyGHDL/dom/_Utils.py @@ -30,12 +30,14 @@ # # SPDX-License-Identifier: GPL-2.0-or-later # ============================================================================ +from pyGHDL.libghdl._types import Iir from pydecor import export from pyVHDLModel.VHDLModel import Mode -from pyGHDL.libghdl import LibGHDLException, name_table +from pyGHDL.libghdl import LibGHDLException, name_table, files_map from pyGHDL.libghdl.vhdl import nodes +from pyGHDL.dom.Misc import Position __all__ = [] @@ -50,22 +52,34 @@ __MODE_TRANSLATION = { @export -def GetIirKindOfNode(node) -> nodes.Iir_Kind: +def GetIirKindOfNode(node: Iir) -> nodes.Iir_Kind: kind: int = nodes.Get_Kind(node) return nodes.Iir_Kind(kind) @export -def NodeToName(node) -> str: +def GetNameOfNode(node: Iir) -> str: """Return the python string from node :obj:`node` identifier""" identifier = nodes.Get_Identifier(node) return name_table.Get_Name_Ptr(identifier) @export -def GetModeOfNode(node) -> Mode: +def GetModeOfNode(node: Iir) -> Mode: """Return the mode of a :obj:`port`.""" try: return __MODE_TRANSLATION[nodes.Get_Mode(node)] except KeyError: raise LibGHDLException("Unknown mode.") + + +@export +def GetPositionOfNode(node: Iir) -> Position: + 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/formatting/prettyprint.py b/pyGHDL/dom/formatting/prettyprint.py index 1577edca0..f19125811 100644 --- a/pyGHDL/dom/formatting/prettyprint.py +++ b/pyGHDL/dom/formatting/prettyprint.py @@ -2,15 +2,19 @@ from typing import List, Union from pydecor import export +from pyGHDL.dom.Misc import Alias +from pyGHDL.dom.Subprogram import Procedure +from pyGHDL.dom.Type import IntegerType, SubType from pyVHDLModel.VHDLModel import ( GenericInterfaceItem, NamedEntity, PortInterfaceItem, WithDefaultExpression, + Function, ) from pyGHDL import GHDLBaseException -from pyGHDL.dom.Misc import Document, Design, Library +from pyGHDL.dom.NonStandard import Document, Design, Library from pyGHDL.dom.DesignUnit import ( Entity, Architecture, @@ -18,6 +22,7 @@ from pyGHDL.dom.DesignUnit import ( PackageBody, Configuration, Context, + Component, ) from pyGHDL.dom.Object import Constant, Signal from pyGHDL.dom.InterfaceItem import ( @@ -161,6 +166,23 @@ class PrettyPrint: return buffer + def formatComponent(self, component: Component, level: int = 0) -> StringBuffer: + buffer = [] + prefix = " " * level + buffer.append( + "{prefix}- Component: {name}".format(name=component.Name, prefix=prefix) + ) + buffer.append("{prefix} Generics:".format(prefix=prefix)) + for generic in component.GenericItems: + for line in self.formatGeneric(generic, level + 1): + buffer.append(line) + buffer.append("{prefix} Ports:".format(prefix=prefix)) + for port in component.PortItems: + for line in self.formatPort(port, level + 1): + buffer.append(line) + + return buffer + def formatPackage(self, package: Package, level: int = 0) -> StringBuffer: buffer = [] prefix = " " * level @@ -293,8 +315,52 @@ class PrettyPrint: else "", ) ) + elif isinstance(item, IntegerType): + buffer.append( + "{prefix}- type {name} is range {range}".format( + prefix=prefix, + name=item.Name, + range="{left!s} to {right!s}".format( + left=item.LeftBound, right=item.RightBound + ), + ) + ) + elif isinstance(item, SubType): + buffer.append( + "{prefix}- subtype {name} is ?????".format( + prefix=prefix, + name=item.Name, + ) + ) + elif isinstance(item, Alias): + buffer.append( + "{prefix}- alias {name} is ?????".format( + prefix=prefix, + name=item.Name, + ) + ) + elif isinstance(item, Function): + buffer.append( + "{prefix}- function {name} return {returnType!s}".format( + prefix=prefix, name=item.Name, returnType=item.ReturnType + ) + ) + elif isinstance(item, Procedure): + buffer.append( + "{prefix}- procedure {name}".format( + prefix=prefix, + name=item.Name, + ) + ) + elif isinstance(item, Component): + for line in self.formatComponent(item, level): + buffer.append(line) else: - raise PrettyPrintException("Unhandled declared item kind.") + raise PrettyPrintException( + "Unhandled declared item kind '{name}'.".format( + name=item.__class__.__name__ + ) + ) return buffer diff --git a/pyGHDL/requirements.txt b/pyGHDL/requirements.txt index f12715412..e6070f92e 100644 --- a/pyGHDL/requirements.txt +++ b/pyGHDL/requirements.txt @@ -1,2 +1,2 @@ pydecor>=2.0.1 -pyVHDLModel==0.10.1 +pyVHDLModel==0.10.2 diff --git a/testsuite/pyunit/Current.vhdl b/testsuite/pyunit/Current.vhdl index 5a677546e..8653cb088 100644 --- a/testsuite/pyunit/Current.vhdl +++ b/testsuite/pyunit/Current.vhdl @@ -20,7 +20,7 @@ end entity entity_1; architecture behav of entity_1 is constant MAX : positive := -25; - signal rst : std_logic := 'U'; + signal rst : std_logic := foo'('U'); type newInt is range -4 to 3; subtype uint8 is integer range 0 to 255; @@ -45,7 +45,7 @@ begin end architecture behav; package package_1 is - constant ghdl : float := (3, 5, 0 => 5, 3 => 4, name => 10); -- 2.3; + constant ghdl : float := (3, 5, 0 to 2 => 5, 3 => 4, name => 10); -- 2.3; end package; package body package_1 is diff --git a/testsuite/pyunit/dom/Expressions.py b/testsuite/pyunit/dom/Expressions.py index 3a4f658af..a7afb30ba 100644 --- a/testsuite/pyunit/dom/Expressions.py +++ b/testsuite/pyunit/dom/Expressions.py @@ -5,8 +5,8 @@ from unittest import TestCase from pyGHDL.dom.DesignUnit import Package from pyGHDL.dom import Expression -from pyGHDL.dom.Misc import Design, Document -from pyGHDL.dom.Symbol import SimpleObjectSymbol +from pyGHDL.dom.NonStandard import Design, Document +from pyGHDL.dom.Symbol import SimpleObjectOrFunctionCallSymbol from pyGHDL.dom.Object import Constant from pyGHDL.dom.Expression import InverseExpression @@ -39,7 +39,7 @@ class Expressions(TestCase): item: Constant = package.DeclaredItems[0] default: Expression = item.DefaultExpression self.assertTrue(isinstance(default, InverseExpression)) - self.assertTrue(isinstance(default.Operand, SimpleObjectSymbol)) + self.assertTrue(isinstance(default.Operand, SimpleObjectOrFunctionCallSymbol)) self.assertTrue(default.Operand.SymbolName == "true") # def test_Aggregare(self): @@ -66,5 +66,5 @@ class Expressions(TestCase): # item: Constant = package.DeclaredItems[0] # default: Expression = item.DefaultExpression # self.assertTrue(isinstance(default, InverseExpression)) - # self.assertTrue(isinstance(default.Operand, SimpleObjectSymbol)) + # self.assertTrue(isinstance(default.Operand, SimpleObjectOrFunctionCallSymbol)) # self.assertTrue(default.Operand.SymbolName == "true") diff --git a/testsuite/pyunit/dom/Literals.py b/testsuite/pyunit/dom/Literals.py index 7eb80abaa..c542ebfe5 100644 --- a/testsuite/pyunit/dom/Literals.py +++ b/testsuite/pyunit/dom/Literals.py @@ -2,7 +2,7 @@ from pathlib import Path from textwrap import dedent from unittest import TestCase -from pyGHDL.dom.Misc import Design, Document +from pyGHDL.dom.NonStandard import Design, Document from pyGHDL.dom.Object import Constant from pyGHDL.dom.Literal import IntegerLiteral diff --git a/testsuite/pyunit/dom/SimpleEntity.py b/testsuite/pyunit/dom/SimpleEntity.py index 252032f9e..8199fe7cc 100644 --- a/testsuite/pyunit/dom/SimpleEntity.py +++ b/testsuite/pyunit/dom/SimpleEntity.py @@ -1,7 +1,7 @@ from pathlib import Path from unittest import TestCase -from pyGHDL.dom.Misc import Design, Library, Document +from pyGHDL.dom.NonStandard import Design, Document if __name__ == "__main__": diff --git a/testsuite/pyunit/dom/SimplePackage.py b/testsuite/pyunit/dom/SimplePackage.py index 212e0402d..5b16e74b8 100644 --- a/testsuite/pyunit/dom/SimplePackage.py +++ b/testsuite/pyunit/dom/SimplePackage.py @@ -1,7 +1,7 @@ from pathlib import Path from unittest import TestCase -from pyGHDL.dom.Misc import Design, Document +from pyGHDL.dom.NonStandard import Design, Document if __name__ == "__main__": |