From 93bf628dc6178674d01255b2b609245605b0aca4 Mon Sep 17 00:00:00 2001 From: Patrick Lehmann Date: Mon, 28 Nov 2022 23:12:09 +0100 Subject: Added method to get associated comments of an iir node. --- pyGHDL/dom/_Utils.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/pyGHDL/dom/_Utils.py b/pyGHDL/dom/_Utils.py index 0349a11ef..b61168418 100644 --- a/pyGHDL/dom/_Utils.py +++ b/pyGHDL/dom/_Utils.py @@ -13,7 +13,7 @@ # # License: # ============================================================================ -# Copyright (C) 2019-2021 Tristan Gingold +# Copyright (C) 2019-2022 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 @@ -34,7 +34,7 @@ from pyTooling.Decorators import export from pyVHDLModel.SyntaxModel import Mode -from pyGHDL.libghdl import LibGHDLException, name_table, errorout_memory +from pyGHDL.libghdl import LibGHDLException, name_table, errorout_memory, files_map, file_comments from pyGHDL.libghdl._types import Iir from pyGHDL.libghdl.vhdl import nodes, utils from pyGHDL.libghdl.vhdl.nodes import Null_Iir @@ -87,6 +87,17 @@ def GetNameOfNode(node: Iir) -> str: return name_table.Get_Name_Ptr(identifier) +@export +def GetDocumentationOfNode(node: Iir) -> str: + file = files_map.Location_To_File(nodes.Get_Location(node)) + idx = file_comments.Find_First_Comment(file, node) + documentation = "" + while idx != file_comments.No_Comment_Index: + documentation += file_comments.Get_Comment(file, idx) + idx = file_comments.Get_Next_Comment(file, idx) + + return documentation + @export def GetModeOfNode(node: Iir) -> Mode: """Return the mode of a :obj:`node`.""" -- cgit v1.2.3 From 3a3e8e5fded027c1dc6e3566c5ad9a30e8bc5297 Mon Sep 17 00:00:00 2001 From: Patrick Lehmann Date: Mon, 28 Nov 2022 23:16:11 +0100 Subject: Added handling of associated documentation comments. --- pyGHDL/dom/Attribute.py | 17 ++++--- pyGHDL/dom/DesignUnit.py | 54 ++++++++++++++-------- pyGHDL/dom/InterfaceItem.py | 110 +++++++++++++++++--------------------------- pyGHDL/dom/Misc.py | 16 +++---- pyGHDL/dom/NonStandard.py | 11 +++-- pyGHDL/dom/Object.py | 90 +++++++++++------------------------- pyGHDL/dom/Subprogram.py | 16 ++++--- pyGHDL/dom/Type.py | 10 +--- 8 files changed, 141 insertions(+), 183 deletions(-) diff --git a/pyGHDL/dom/Attribute.py b/pyGHDL/dom/Attribute.py index 86be400ac..576b05245 100644 --- a/pyGHDL/dom/Attribute.py +++ b/pyGHDL/dom/Attribute.py @@ -13,7 +13,7 @@ # # License: # ============================================================================ -# Copyright (C) 2019-2021 Tristan Gingold +# Copyright (C) 2019-2022 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 @@ -46,7 +46,7 @@ from pyGHDL.libghdl._types import Iir from pyGHDL.libghdl.vhdl import nodes from pyGHDL.libghdl.vhdl.tokens import Tok from pyGHDL.dom import DOMMixin, Position, DOMException, Expression -from pyGHDL.dom._Utils import GetNameOfNode, GetIirKindOfNode +from pyGHDL.dom._Utils import GetNameOfNode, GetIirKindOfNode, GetDocumentationOfNode from pyGHDL.dom._Translate import GetNameFromNode, GetExpressionFromNode from pyGHDL.dom.Names import SimpleName from pyGHDL.dom.Symbol import SimpleSubtypeSymbol @@ -54,18 +54,19 @@ from pyGHDL.dom.Symbol import SimpleSubtypeSymbol @export class Attribute(VHDLModel_Attribute, DOMMixin): - def __init__(self, node: Iir, identifier: str, subtype: SubtypeOrSymbol): - super().__init__(identifier, subtype) + def __init__(self, node: Iir, identifier: str, subtype: SubtypeOrSymbol, documentation: str = None): + super().__init__(identifier, subtype, documentation) DOMMixin.__init__(self, node) @classmethod def parse(cls, attributeNode: Iir) -> "Attribute": name = GetNameOfNode(attributeNode) + documentation = GetDocumentationOfNode(attributeNode) subtypeMark = nodes.Get_Type_Mark(attributeNode) subtypeName = GetNameOfNode(subtypeMark) subtype = SimpleSubtypeSymbol(subtypeMark, subtypeName) - return cls(attributeNode, name, subtype) + return cls(attributeNode, name, subtype, documentation) _TOKEN_TRANSLATION = { @@ -102,14 +103,16 @@ class AttributeSpecification(VHDLModel_AttributeSpecification, DOMMixin): attribute: Name, entityClass: EntityClass, expression: Expression, + documentation: str = None ): - super().__init__(identifiers, attribute, entityClass, expression) + super().__init__(identifiers, attribute, entityClass, expression, documentation) DOMMixin.__init__(self, node) @classmethod def parse(cls, attributeNode: Iir) -> "AttributeSpecification": attributeDesignator = nodes.Get_Attribute_Designator(attributeNode) attributeName = GetNameFromNode(attributeDesignator) + documentation = GetDocumentationOfNode(attributeNode) names = [] entityNameList = nodes.Get_Entity_Name_List(attributeNode) @@ -136,4 +139,4 @@ class AttributeSpecification(VHDLModel_AttributeSpecification, DOMMixin): expression = GetExpressionFromNode(nodes.Get_Expression(attributeNode)) - return cls(attributeNode, names, attributeName, entityClass, expression) + return cls(attributeNode, names, attributeName, entityClass, expression, documentation) diff --git a/pyGHDL/dom/DesignUnit.py b/pyGHDL/dom/DesignUnit.py index f45cb8340..853184450 100644 --- a/pyGHDL/dom/DesignUnit.py +++ b/pyGHDL/dom/DesignUnit.py @@ -13,7 +13,7 @@ # # License: # ============================================================================ -# Copyright (C) 2019-2021 Tristan Gingold +# Copyright (C) 2019-2022 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 @@ -66,7 +66,7 @@ from pyGHDL.libghdl import utils from pyGHDL.libghdl._types import Iir from pyGHDL.libghdl.vhdl import nodes from pyGHDL.dom import DOMMixin, Position, DOMException -from pyGHDL.dom._Utils import GetNameOfNode +from pyGHDL.dom._Utils import GetNameOfNode, GetDocumentationOfNode from pyGHDL.dom._Translate import ( GetGenericsFromChainedNodes, GetPortsFromChainedNodes, @@ -132,13 +132,15 @@ class Entity(VHDLModel_Entity, DOMMixin): portItems: Iterable[PortInterfaceItem] = None, declaredItems: Iterable = None, statements: Iterable["ConcurrentStatement"] = None, + documentation: str = None ): - super().__init__(identifier, contextItems, genericItems, portItems, declaredItems, statements) + super().__init__(identifier, contextItems, genericItems, portItems, declaredItems, statements, documentation) DOMMixin.__init__(self, node) @classmethod def parse(cls, entityNode: Iir, contextItems: Iterable[ContextUnion]): name = GetNameOfNode(entityNode) + documentation = GetDocumentationOfNode(entityNode) generics = GetGenericsFromChainedNodes(nodes.Get_Generic_Chain(entityNode)) ports = GetPortsFromChainedNodes(nodes.Get_Port_Chain(entityNode)) declaredItems = GetDeclaredItemsFromChainedNodes(nodes.Get_Declaration_Chain(entityNode), "entity", name) @@ -148,7 +150,7 @@ class Entity(VHDLModel_Entity, DOMMixin): # FIXME: read use clauses - return cls(entityNode, name, contextItems, generics, ports, declaredItems, statements) + return cls(entityNode, name, contextItems, generics, ports, declaredItems, statements, documentation) @export @@ -161,13 +163,15 @@ class Architecture(VHDLModel_Architecture, DOMMixin): contextItems: Iterable[ContextUnion] = None, declaredItems: Iterable = None, statements: Iterable["ConcurrentStatement"] = None, + documentation: str = None ): - super().__init__(identifier, entity, contextItems, declaredItems, statements) + super().__init__(identifier, entity, contextItems, declaredItems, statements, documentation) DOMMixin.__init__(self, node) @classmethod def parse(cls, architectureNode: Iir, contextItems: Iterable[ContextUnion]): name = GetNameOfNode(architectureNode) + documentation = GetDocumentationOfNode(architectureNode) entityNameNode = nodes.Get_Entity_Name(architectureNode) entityName = GetNameOfNode(entityNameNode) entity = EntitySymbol(entityNameNode, SimpleName(entityNameNode, entityName)) @@ -180,7 +184,7 @@ class Architecture(VHDLModel_Architecture, DOMMixin): # FIXME: read use clauses - return cls(architectureNode, name, entity, contextItems, declaredItems, statements) + return cls(architectureNode, name, entity, contextItems, declaredItems, statements, documentation) @export @@ -191,17 +195,19 @@ class Component(VHDLModel_Component, DOMMixin): identifier: str, genericItems: Iterable[GenericInterfaceItem] = None, portItems: Iterable[PortInterfaceItem] = None, + documentation: str = None ): - super().__init__(identifier, genericItems, portItems) + super().__init__(identifier, genericItems, portItems, documentation) DOMMixin.__init__(self, node) @classmethod def parse(cls, componentNode: Iir): name = GetNameOfNode(componentNode) + documentation = GetDocumentationOfNode(componentNode) generics = GetGenericsFromChainedNodes(nodes.Get_Generic_Chain(componentNode)) ports = GetPortsFromChainedNodes(nodes.Get_Port_Chain(componentNode)) - return cls(componentNode, name, generics, ports) + return cls(componentNode, name, generics, ports, documentation) @export @@ -213,13 +219,15 @@ class Package(VHDLModel_Package, DOMMixin): contextItems: Iterable[ContextUnion] = None, genericItems: Iterable[GenericInterfaceItem] = None, declaredItems: Iterable = None, + documentation: str = None ): - super().__init__(identifier, contextItems, genericItems, declaredItems) + super().__init__(identifier, contextItems, genericItems, declaredItems, documentation) DOMMixin.__init__(self, node) @classmethod def parse(cls, packageNode: Iir, contextItems: Iterable[ContextUnion]): name = GetNameOfNode(packageNode) + documentation = GetDocumentationOfNode(packageNode) packageHeader = nodes.Get_Package_Header(packageNode) if packageHeader is not nodes.Null_Iir: @@ -231,7 +239,7 @@ class Package(VHDLModel_Package, DOMMixin): # FIXME: read use clauses - return cls(packageNode, name, contextItems, generics, declaredItems) + return cls(packageNode, name, contextItems, generics, declaredItems, documentation) @export @@ -242,18 +250,20 @@ class PackageBody(VHDLModel_PackageBody, DOMMixin): identifier: str, contextItems: Iterable[ContextUnion] = None, declaredItems: Iterable = None, + documentation: str = None ): - super().__init__(identifier, contextItems, declaredItems) + super().__init__(identifier, contextItems, declaredItems, documentation) DOMMixin.__init__(self, node) @classmethod def parse(cls, packageBodyNode: Iir, contextItems: Iterable[ContextUnion]): name = GetNameOfNode(packageBodyNode) + documentation = GetDocumentationOfNode(packageBodyNode) declaredItems = GetDeclaredItemsFromChainedNodes(nodes.Get_Declaration_Chain(packageBodyNode), "package", name) # FIXME: read use clauses - return cls(packageBodyNode, name, contextItems, declaredItems) + return cls(packageBodyNode, name, contextItems, declaredItems, documentation) @export @@ -264,13 +274,15 @@ class PackageInstantiation(VHDLModel_PackageInstantiation, DOMMixin): identifier: str, uninstantiatedPackageName: Name, # genericItems: List[GenericInterfaceItem] = None, + documentation: str = None ): - super().__init__(identifier, uninstantiatedPackageName) + super().__init__(identifier, uninstantiatedPackageName, documentation) DOMMixin.__init__(self, node) @classmethod def parse(cls, packageNode: Iir): name = GetNameOfNode(packageNode) + documentation = GetDocumentationOfNode(packageNode) uninstantiatedPackageName = nodes.Get_Uninstantiated_Package_Name(packageNode) # FIXME: read use clauses (does it apply here too?) @@ -278,7 +290,7 @@ class PackageInstantiation(VHDLModel_PackageInstantiation, DOMMixin): # FIXME: read generic map # genericAssociations = GetGenericMapAspect(nodes.Get_Generic_Map_Aspect_Chain(instantiationNode)) - return cls(packageNode, name, uninstantiatedPackageName) + return cls(packageNode, name, uninstantiatedPackageName, documentation) @export @@ -289,8 +301,9 @@ class Context(VHDLModel_Context, DOMMixin): identifier: str, libraryReferences: Iterable[LibraryClause] = None, packageReferences: Iterable[UseClause] = None, + documentation: str = None ): - super().__init__(identifier, libraryReferences, packageReferences) + super().__init__(identifier, libraryReferences, packageReferences, documentation) DOMMixin.__init__(self, node) @classmethod @@ -298,6 +311,7 @@ class Context(VHDLModel_Context, DOMMixin): from pyGHDL.dom._Utils import GetIirKindOfNode name = GetNameOfNode(contextNode) + documentation = GetDocumentationOfNode(contextNode) items = [] names = [] @@ -316,7 +330,7 @@ class Context(VHDLModel_Context, DOMMixin): pos = Position.parse(item) raise DOMException(f"Unknown context item kind '{kind.name}' in context at line {pos.Line}.") - return cls(contextNode, name, items) + return cls(contextNode, name, items, documentation) @export @@ -326,15 +340,17 @@ class Configuration(VHDLModel_Configuration, DOMMixin): node: Iir, identifier: str, contextItems: Iterable[Context] = None, + documentation: str = None ): - super().__init__(identifier, contextItems) + super().__init__(identifier, contextItems, documentation) DOMMixin.__init__(self, node) @classmethod def parse(cls, configurationNode: Iir, contextItems: Iterable[Context]): - name = GetNameOfNode(configurationNode) + name = GetNameOfNode(configurationNode), + documentation = GetDocumentationOfNode(configurationNode) # FIXME: read use clauses # FIXME: read specifications - return cls(configurationNode, name, contextItems) + return cls(configurationNode, name, contextItems, documentation) diff --git a/pyGHDL/dom/InterfaceItem.py b/pyGHDL/dom/InterfaceItem.py index 66a8fe37b..e42c8dcb2 100644 --- a/pyGHDL/dom/InterfaceItem.py +++ b/pyGHDL/dom/InterfaceItem.py @@ -13,7 +13,7 @@ # # License: # ============================================================================ -# Copyright (C) 2019-2021 Tristan Gingold +# Copyright (C) 2019-2022 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 @@ -53,7 +53,7 @@ from pyVHDLModel.SyntaxModel import ( from pyGHDL.libghdl._types import Iir from pyGHDL.libghdl.vhdl import nodes from pyGHDL.dom import DOMMixin -from pyGHDL.dom._Utils import GetNameOfNode, GetModeOfNode +from pyGHDL.dom._Utils import GetNameOfNode, GetModeOfNode, GetDocumentationOfNode from pyGHDL.dom._Translate import GetSubtypeIndicationFromNode, GetExpressionFromNode @@ -69,27 +69,21 @@ class GenericConstantInterfaceItem(VHDLModel_GenericConstantInterfaceItem, DOMMi mode: Mode, subtype: SubtypeOrSymbol, defaultExpression: ExpressionUnion, + documentation: str = None ): - super().__init__(identifiers, mode, subtype, defaultExpression) + super().__init__(identifiers, mode, subtype, defaultExpression, documentation) DOMMixin.__init__(self, node) @classmethod def parse(cls, genericNode: Iir) -> "GenericConstantInterfaceItem": name = GetNameOfNode(genericNode) + documentation = GetDocumentationOfNode(genericNode) mode = GetModeOfNode(genericNode) subtypeIndication = GetSubtypeIndicationFromNode(genericNode, "generic", name) default = nodes.Get_Default_Value(genericNode) value = GetExpressionFromNode(default) if default else None - return cls( - genericNode, - [ - name, - ], - mode, - subtypeIndication, - value, - ) + return cls(genericNode, [name], mode, subtypeIndication, value, documentation) @export @@ -98,15 +92,17 @@ class GenericTypeInterfaceItem(VHDLModel_GenericTypeInterfaceItem, DOMMixin): self, node: Iir, identifier: str, + documentation: str = None ): - super().__init__(identifier) + super().__init__(identifier, documentation) DOMMixin.__init__(self, node) @classmethod def parse(cls, genericNode: Iir) -> "GenericTypeInterfaceItem": name = GetNameOfNode(genericNode) + documentation = GetDocumentationOfNode(genericNode) - return cls(genericNode, name) + return cls(genericNode, name, documentation) @export @@ -115,15 +111,17 @@ class GenericPackageInterfaceItem(VHDLModel_GenericPackageInterfaceItem, DOMMixi self, node: Iir, name: str, + documentation: str = None ): - super().__init__(name) + super().__init__(name, documentation) DOMMixin.__init__(self, node) @classmethod def parse(cls, genericNode: Iir) -> "GenericPackageInterfaceItem": name = GetNameOfNode(genericNode) + documentation = GetDocumentationOfNode(genericNode) - return cls(genericNode, name) + return cls(genericNode, name, documentation) @export @@ -132,15 +130,17 @@ class GenericProcedureInterfaceItem(VHDLModel_GenericProcedureInterfaceItem, DOM self, node: Iir, identifier: str, + documentation: str = None ): - super().__init__(identifier) + super().__init__(identifier, documentation) DOMMixin.__init__(self, node) @classmethod def parse(cls, genericNode: Iir) -> "GenericProcedureInterfaceItem": name = GetNameOfNode(genericNode) + documentation = GetDocumentationOfNode(genericNode) - return cls(genericNode, name) + return cls(genericNode, name, documentation) @export @@ -149,15 +149,17 @@ class GenericFunctionInterfaceItem(VHDLModel_GenericFunctionInterfaceItem, DOMMi self, node: Iir, identifier: str, + documentation: str = None ): - super().__init__(identifier) + super().__init__(identifier, documentation) DOMMixin.__init__(self, node) @classmethod def parse(cls, genericNode: Iir) -> "GenericFunctionInterfaceItem": name = GetNameOfNode(genericNode) + documentation = GetDocumentationOfNode(genericNode) - return cls(genericNode, name) + return cls(genericNode, name, documentation) @export @@ -169,28 +171,22 @@ class PortSignalInterfaceItem(VHDLModel_PortSignalInterfaceItem, DOMMixin): mode: Mode, subtype: SubtypeOrSymbol, defaultExpression: ExpressionUnion = None, + documentation: str = None ): - super().__init__(identifiers, mode, subtype, defaultExpression) + super().__init__(identifiers, mode, subtype, defaultExpression, documentation) DOMMixin.__init__(self, node) @classmethod def parse(cls, portNode: Iir) -> "PortSignalInterfaceItem": name = GetNameOfNode(portNode) + documentation = GetDocumentationOfNode(portNode) mode = GetModeOfNode(portNode) subtypeIndication = GetSubtypeIndicationFromNode(portNode, "port", name) defaultValue = nodes.Get_Default_Value(portNode) value = GetExpressionFromNode(defaultValue) if defaultValue != nodes.Null_Iir else None - return cls( - portNode, - [ - name, - ], - mode, - subtypeIndication, - value, - ) + return cls(portNode, [name], mode, subtypeIndication, value, documentation) @export @@ -202,28 +198,22 @@ class ParameterConstantInterfaceItem(VHDLModel_ParameterConstantInterfaceItem, D mode: Mode, subtype: SubtypeOrSymbol, defaultExpression: ExpressionUnion = None, + documentation: str = None ): - super().__init__(identifiers, mode, subtype, defaultExpression) + super().__init__(identifiers, mode, subtype, defaultExpression, documentation) DOMMixin.__init__(self, node) @classmethod def parse(cls, parameterNode: Iir) -> "ParameterConstantInterfaceItem": name = GetNameOfNode(parameterNode) + documentation = GetDocumentationOfNode(parameterNode) mode = GetModeOfNode(parameterNode) subtypeIndication = GetSubtypeIndicationFromNode(parameterNode, "parameter", name) defaultValue = nodes.Get_Default_Value(parameterNode) value = GetExpressionFromNode(defaultValue) if defaultValue != nodes.Null_Iir else None - return cls( - parameterNode, - [ - name, - ], - mode, - subtypeIndication, - value, - ) + return cls(parameterNode, [name], mode, subtypeIndication, value, documentation) @export @@ -235,28 +225,22 @@ class ParameterVariableInterfaceItem(VHDLModel_ParameterVariableInterfaceItem, D mode: Mode, subtype: SubtypeOrSymbol, defaultExpression: ExpressionUnion = None, + documentation: str = None ): - super().__init__(identifiers, mode, subtype, defaultExpression) + super().__init__(identifiers, mode, subtype, defaultExpression, documentation) DOMMixin.__init__(self, node) @classmethod def parse(cls, parameterNode: Iir) -> "ParameterVariableInterfaceItem": name = GetNameOfNode(parameterNode) + documentation = GetDocumentationOfNode(parameterNode) mode = GetModeOfNode(parameterNode) subtypeIndication = GetSubtypeIndicationFromNode(parameterNode, "parameter", name) defaultValue = nodes.Get_Default_Value(parameterNode) value = GetExpressionFromNode(defaultValue) if defaultValue != nodes.Null_Iir else None - return cls( - parameterNode, - [ - name, - ], - mode, - subtypeIndication, - value, - ) + return cls(parameterNode, [name], mode, subtypeIndication, value, documentation) @export @@ -268,28 +252,22 @@ class ParameterSignalInterfaceItem(VHDLModel_ParameterSignalInterfaceItem, DOMMi mode: Mode, subtype: SubtypeOrSymbol, defaultExpression: ExpressionUnion = None, + documentation: str = None ): - super().__init__(identifiers, mode, subtype, defaultExpression) + super().__init__(identifiers, mode, subtype, defaultExpression, documentation) DOMMixin.__init__(self, node) @classmethod def parse(cls, parameterNode: Iir) -> "ParameterSignalInterfaceItem": name = GetNameOfNode(parameterNode) + documentation = GetDocumentationOfNode(parameterNode) mode = GetModeOfNode(parameterNode) subtypeIndication = GetSubtypeIndicationFromNode(parameterNode, "parameter", name) defaultValue = nodes.Get_Default_Value(parameterNode) value = GetExpressionFromNode(defaultValue) if defaultValue != nodes.Null_Iir else None - return cls( - parameterNode, - [ - name, - ], - mode, - subtypeIndication, - value, - ) + return cls(parameterNode, [name], mode, subtypeIndication, value, documentation) @export @@ -299,19 +277,15 @@ class ParameterFileInterfaceItem(VHDLModel_ParameterFileInterfaceItem, DOMMixin) node: Iir, identifiers: List[str], subtype: SubtypeOrSymbol, + documentation: str = None ): - super().__init__(identifiers, subtype) + super().__init__(identifiers, subtype, documentation) DOMMixin.__init__(self, node) @classmethod def parse(cls, parameterNode: Iir) -> "ParameterFileInterfaceItem": name = GetNameOfNode(parameterNode) + documentation = GetDocumentationOfNode(parameterNode) subtypeIndication = GetSubtypeIndicationFromNode(parameterNode, "parameter", name) - return cls( - parameterNode, - [ - name, - ], - subtypeIndication, - ) + return cls(parameterNode, [name], subtypeIndication, documentation) diff --git a/pyGHDL/dom/Misc.py b/pyGHDL/dom/Misc.py index d6fc08524..8f85db222 100644 --- a/pyGHDL/dom/Misc.py +++ b/pyGHDL/dom/Misc.py @@ -13,7 +13,7 @@ # # License: # ============================================================================ -# Copyright (C) 2019-2021 Tristan Gingold +# Copyright (C) 2019-2022 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 @@ -42,22 +42,22 @@ from pyVHDLModel.SyntaxModel import ( ) from pyGHDL.libghdl._types import Iir from pyGHDL.dom import DOMMixin -from pyGHDL.dom._Utils import GetNameOfNode - +from pyGHDL.dom._Utils import GetNameOfNode, GetDocumentationOfNode __all__ = [] @export class Alias(VHDLModel_Alias, DOMMixin): - def __init__(self, node: Iir, aliasName: str): - super().__init__(aliasName) + def __init__(self, node: Iir, aliasName: str, documentation: str = None): + super().__init__(aliasName, documentation) DOMMixin.__init__(self, node) @classmethod - def parse(cls, node: Iir): - aliasName = GetNameOfNode(node) + def parse(cls, aliasNode: Iir): + aliasName = GetNameOfNode(aliasNode) + documentation = GetDocumentationOfNode(aliasNode) # FIXME: add an implementation - return cls(node, aliasName) + return cls(aliasNode, aliasName) diff --git a/pyGHDL/dom/NonStandard.py b/pyGHDL/dom/NonStandard.py index c55786d54..7a38d60ce 100644 --- a/pyGHDL/dom/NonStandard.py +++ b/pyGHDL/dom/NonStandard.py @@ -13,7 +13,7 @@ # # License: # ============================================================================ -# Copyright (C) 2019-2021 Tristan Gingold +# Copyright (C) 2019-2022 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 @@ -42,7 +42,6 @@ from typing import Any from pyTooling.Decorators import export -from pyGHDL.dom.Names import SimpleName from pyVHDLModel.SyntaxModel import ( Design as VHDLModel_Design, Library as VHDLModel_Library, @@ -61,9 +60,12 @@ from pyGHDL.libghdl import ( utils, files_map_editor, ) -from pyGHDL.libghdl.vhdl import nodes, sem_lib, parse +from pyGHDL.libghdl.flags import Flag_Gather_Comments +from pyGHDL.libghdl.vhdl import nodes, sem_lib +from pyGHDL.libghdl.vhdl.parse import Flag_Parse_Parenthesis from pyGHDL.dom import DOMException, Position from pyGHDL.dom._Utils import GetIirKindOfNode, CheckForErrors, GetNameOfNode +from pyGHDL.dom.Names import SimpleName from pyGHDL.dom.DesignUnit import ( Entity, Architecture, @@ -100,7 +102,8 @@ class Design(VHDLModel_Design): libghdl_set_option("--std=08") libghdl_set_option("--ams") - parse.Flag_Parse_Parenthesis.value = True + Flag_Gather_Comments.value = True + Flag_Parse_Parenthesis.value = True # Finish initialization. This will load the standard package. if libghdl_analyze_init_status() != 0: diff --git a/pyGHDL/dom/Object.py b/pyGHDL/dom/Object.py index 6d3472a6f..162bc8bef 100644 --- a/pyGHDL/dom/Object.py +++ b/pyGHDL/dom/Object.py @@ -13,7 +13,7 @@ # # License: # ============================================================================ -# Copyright (C) 2019-2021 Tristan Gingold +# Copyright (C) 2019-2022 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 @@ -48,7 +48,7 @@ from pyVHDLModel.SyntaxModel import ( 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._Utils import GetNameOfNode, GetDocumentationOfNode __all__ = [] @@ -61,8 +61,9 @@ class Constant(VHDLModel_Constant, DOMMixin): identifiers: List[str], subtype: SubtypeOrSymbol, defaultExpression: ExpressionUnion, + documentation: str = None ): - super().__init__(identifiers, subtype, defaultExpression) + super().__init__(identifiers, subtype, defaultExpression, documentation) DOMMixin.__init__(self, node) @classmethod @@ -73,33 +74,21 @@ class Constant(VHDLModel_Constant, DOMMixin): ) name = GetNameOfNode(constantNode) + documentation = GetDocumentationOfNode(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, - ) + return cls(constantNode, [name], subtypeIndication, defaultExpression, documentation) else: - return DeferredConstant( - constantNode, - [ - name, - ], - subtypeIndication, - ) + return DeferredConstant(constantNode, [name], subtypeIndication, documentation) @export class DeferredConstant(VHDLModel_DeferredConstant, DOMMixin): - def __init__(self, node: Iir, identifiers: List[str], subtype: SubtypeOrSymbol): - super().__init__(identifiers, subtype) + def __init__(self, node: Iir, identifiers: List[str], subtype: SubtypeOrSymbol, documentation: str = None): + super().__init__(identifiers, subtype, documentation) DOMMixin.__init__(self, node) @classmethod @@ -107,15 +96,10 @@ class DeferredConstant(VHDLModel_DeferredConstant, DOMMixin): from pyGHDL.dom._Translate import GetSubtypeIndicationFromNode name = GetNameOfNode(constantNode) + documentation = GetDocumentationOfNode(constantNode) subtypeIndication = GetSubtypeIndicationFromNode(constantNode, "deferred constant", name) - return cls( - constantNode, - [ - name, - ], - subtypeIndication, - ) + return cls(constantNode, [name], subtypeIndication, documentation) @export @@ -126,8 +110,9 @@ class Variable(VHDLModel_Variable, DOMMixin): identifiers: List[str], subtype: SubtypeOrSymbol, defaultExpression: ExpressionUnion, + documentation: str = None ): - super().__init__(identifiers, subtype, defaultExpression) + super().__init__(identifiers, subtype, defaultExpression, documentation) DOMMixin.__init__(self, node) @classmethod @@ -138,26 +123,20 @@ class Variable(VHDLModel_Variable, DOMMixin): ) name = GetNameOfNode(variableNode) + documentation = GetDocumentationOfNode(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, - ) + return cls(variableNode, [name], subtypeIndication, defaultExpression, documentation) @export class SharedVariable(VHDLModel_SharedVariable, DOMMixin): - def __init__(self, node: Iir, identifiers: List[str], subtype: SubtypeOrSymbol): - super().__init__(identifiers, subtype) + def __init__(self, node: Iir, identifiers: List[str], subtype: SubtypeOrSymbol, documentation: str = None): + super().__init__(identifiers, subtype, documentation) DOMMixin.__init__(self, node) @classmethod @@ -165,15 +144,10 @@ class SharedVariable(VHDLModel_SharedVariable, DOMMixin): from pyGHDL.dom._Translate import GetSubtypeIndicationFromNode name = GetNameOfNode(variableNode) + documentation = GetDocumentationOfNode(variableNode) subtypeIndication = GetSubtypeIndicationFromNode(variableNode, "variable", name) - return cls( - variableNode, - [ - name, - ], - subtypeIndication, - ) + return cls(variableNode, [name], subtypeIndication, documentation) @export @@ -184,8 +158,9 @@ class Signal(VHDLModel_Signal, DOMMixin): identifiers: List[str], subtype: SubtypeOrSymbol, defaultExpression: ExpressionUnion, + documentation: str = None ): - super().__init__(identifiers, subtype, defaultExpression) + super().__init__(identifiers, subtype, defaultExpression, documentation) DOMMixin.__init__(self, node) @classmethod @@ -196,24 +171,18 @@ class Signal(VHDLModel_Signal, DOMMixin): ) name = GetNameOfNode(signalNode) + documentation = GetDocumentationOfNode(signalNode) subtypeIndication = GetSubtypeIndicationFromNode(signalNode, "signal", name) default = nodes.Get_Default_Value(signalNode) defaultExpression = GetExpressionFromNode(default) if default else None - return cls( - signalNode, - [ - name, - ], - subtypeIndication, - defaultExpression, - ) + return cls(signalNode, [name], subtypeIndication, defaultExpression, documentation) @export class File(VHDLModel_File, DOMMixin): - def __init__(self, node: Iir, identifiers: List[str], subtype: SubtypeOrSymbol): - super().__init__(identifiers, subtype) + def __init__(self, node: Iir, identifiers: List[str], subtype: SubtypeOrSymbol, documentation: str = None): + super().__init__(identifiers, subtype, documentation) DOMMixin.__init__(self, node) @classmethod @@ -221,14 +190,9 @@ class File(VHDLModel_File, DOMMixin): from pyGHDL.dom._Translate import GetSubtypeIndicationFromNode name = GetNameOfNode(fileNode) + documentation = GetDocumentationOfNode(fileNode) subtypeIndication = GetSubtypeIndicationFromNode(fileNode, "file", name) # FIXME: handle file open stuff - return cls( - fileNode, - [ - name, - ], - subtypeIndication, - ) + return cls(fileNode, [name], subtypeIndication, documentation) diff --git a/pyGHDL/dom/Subprogram.py b/pyGHDL/dom/Subprogram.py index 2e9c0116f..ba7ee035a 100644 --- a/pyGHDL/dom/Subprogram.py +++ b/pyGHDL/dom/Subprogram.py @@ -13,7 +13,7 @@ # # License: # ============================================================================ -# Copyright (C) 2019-2021 Tristan Gingold +# Copyright (C) 2019-2022 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 @@ -44,7 +44,7 @@ from pyVHDLModel.SyntaxModel import ( 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._Utils import GetNameOfNode, GetDocumentationOfNode from pyGHDL.dom.Symbol import SimpleSubtypeSymbol @@ -57,8 +57,9 @@ class Function(VHDLModel_Function, DOMMixin): returnType: SubtypeOrSymbol, genericItems: List[GenericInterfaceItem] = None, parameterItems: List[ParameterInterfaceItem] = None, + documentation: str = None ): - super().__init__(functionName) + super().__init__(functionName, documentation) DOMMixin.__init__(self, node) # TODO: move to model @@ -74,6 +75,7 @@ class Function(VHDLModel_Function, DOMMixin): ) functionName = GetNameOfNode(functionNode) + documentation = GetDocumentationOfNode(functionNode) generics = GetGenericsFromChainedNodes(nodes.Get_Generic_Chain(functionNode)) parameters = GetParameterFromChainedNodes(nodes.Get_Interface_Declaration_Chain(functionNode)) @@ -82,7 +84,7 @@ class Function(VHDLModel_Function, DOMMixin): returnTypeName = GetNameOfNode(returnType) returnTypeSymbol = SimpleSubtypeSymbol(returnType, returnTypeName) - return cls(functionNode, functionName, returnTypeSymbol, generics, parameters) + return cls(functionNode, functionName, returnTypeSymbol, generics, parameters, documentation) @export @@ -93,8 +95,9 @@ class Procedure(VHDLModel_Procedure, DOMMixin): procedureName: str, genericItems: List[GenericInterfaceItem] = None, parameterItems: List[ParameterInterfaceItem] = None, + documentation: str = None ): - super().__init__(procedureName) + super().__init__(procedureName, documentation) DOMMixin.__init__(self, node) # TODO: move to model @@ -109,8 +112,9 @@ class Procedure(VHDLModel_Procedure, DOMMixin): ) procedureName = GetNameOfNode(procedureNode) + documentation = GetDocumentationOfNode(procedureNode) generics = GetGenericsFromChainedNodes(nodes.Get_Generic_Chain(procedureNode)) parameters = GetParameterFromChainedNodes(nodes.Get_Interface_Declaration_Chain(procedureNode)) - return cls(procedureNode, procedureName, generics, parameters) + return cls(procedureNode, procedureName, generics, parameters, documentation) diff --git a/pyGHDL/dom/Type.py b/pyGHDL/dom/Type.py index b0f2d1311..555a4b1ae 100644 --- a/pyGHDL/dom/Type.py +++ b/pyGHDL/dom/Type.py @@ -13,7 +13,7 @@ # # License: # ============================================================================ -# Copyright (C) 2019-2021 Tristan Gingold +# Copyright (C) 2019-2022 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 @@ -192,13 +192,7 @@ class RecordTypeElement(VHDLModel_RecordTypeElement, DOMMixin): elementName = GetNameOfNode(elementDeclarationNode) elementType = GetSubtypeIndicationFromNode(elementDeclarationNode, "record element", elementName) - return cls( - elementDeclarationNode, - [ - elementName, - ], - elementType, - ) + return cls(elementDeclarationNode, [elementName], elementType,) @export -- cgit v1.2.3 From 2161dcbb0077057e1da026368ef44e056e637d43 Mon Sep 17 00:00:00 2001 From: Patrick Lehmann Date: Mon, 28 Nov 2022 23:18:48 +0100 Subject: Added comments to test files. --- testsuite/pyunit/SimplePackage.vhdl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/testsuite/pyunit/SimplePackage.vhdl b/testsuite/pyunit/SimplePackage.vhdl index 0571e7060..dca7e15dc 100644 --- a/testsuite/pyunit/SimplePackage.vhdl +++ b/testsuite/pyunit/SimplePackage.vhdl @@ -2,12 +2,14 @@ library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; +-- Documentation before pack_1 package pack_1 is + -- Global constant const_1 constant const_1 : boolean := false; end package; package body pack_1 is - constant const_1 : boolean := true; + constant const_2 : boolean := true; end package body; -- cgit v1.2.3 From 4280385c83d349906e799cf0f32e6e7a4a491124 Mon Sep 17 00:00:00 2001 From: Patrick Lehmann Date: Wed, 30 Nov 2022 23:29:04 +0100 Subject: Collect multiline comments with linebreaks. --- pyGHDL/dom/_Utils.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/pyGHDL/dom/_Utils.py b/pyGHDL/dom/_Utils.py index b61168418..10053db6e 100644 --- a/pyGHDL/dom/_Utils.py +++ b/pyGHDL/dom/_Utils.py @@ -91,12 +91,13 @@ def GetNameOfNode(node: Iir) -> str: def GetDocumentationOfNode(node: Iir) -> str: file = files_map.Location_To_File(nodes.Get_Location(node)) idx = file_comments.Find_First_Comment(file, node) - documentation = "" + documentation = [] while idx != file_comments.No_Comment_Index: - documentation += file_comments.Get_Comment(file, idx) + documentation.append(file_comments.Get_Comment(file, idx)) idx = file_comments.Get_Next_Comment(file, idx) - return documentation + return "\n".join(documentation) + @export def GetModeOfNode(node: Iir) -> Mode: -- cgit v1.2.3 From 3cca269570b68d0edb45dbe256fc6e6360909bf0 Mon Sep 17 00:00:00 2001 From: Patrick Lehmann Date: Wed, 30 Nov 2022 23:29:54 +0100 Subject: Collect file header comments as documentation for the VHDL document. --- pyGHDL/dom/NonStandard.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pyGHDL/dom/NonStandard.py b/pyGHDL/dom/NonStandard.py index 7a38d60ce..eb6afd3c6 100644 --- a/pyGHDL/dom/NonStandard.py +++ b/pyGHDL/dom/NonStandard.py @@ -64,7 +64,7 @@ from pyGHDL.libghdl.flags import Flag_Gather_Comments from pyGHDL.libghdl.vhdl import nodes, sem_lib from pyGHDL.libghdl.vhdl.parse import Flag_Parse_Parenthesis from pyGHDL.dom import DOMException, Position -from pyGHDL.dom._Utils import GetIirKindOfNode, CheckForErrors, GetNameOfNode +from pyGHDL.dom._Utils import GetIirKindOfNode, CheckForErrors, GetNameOfNode, GetDocumentationOfNode from pyGHDL.dom.Names import SimpleName from pyGHDL.dom.DesignUnit import ( Entity, @@ -170,6 +170,7 @@ class Document(VHDLModel_Document): def translate(self): firstUnit = nodes.Get_First_Design_Unit(self.__ghdlFile) + self._documentation = GetDocumentationOfNode(firstUnit) for unit in utils.chain_iter(firstUnit): libraryUnit = nodes.Get_Library_Unit(unit) -- cgit v1.2.3 From aa2bf5500676b29f64ae542553f1ecd84b2dc137 Mon Sep 17 00:00:00 2001 From: Patrick Lehmann Date: Sat, 3 Dec 2022 01:36:34 +0100 Subject: Some f-string changes. --- testsuite/pyunit/libghdl/Initialize.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/testsuite/pyunit/libghdl/Initialize.py b/testsuite/pyunit/libghdl/Initialize.py index 7e3ace869..11bfe9a56 100644 --- a/testsuite/pyunit/libghdl/Initialize.py +++ b/testsuite/pyunit/libghdl/Initialize.py @@ -39,7 +39,7 @@ class Instantiate(TestCase): file_id = name_table.Get_Identifier(str(self._filename)) sfe = files_map.Read_Source_File(name_table.Null_Identifier, file_id) if sfe == files_map.No_Source_File_Entry: - self.fail("Cannot read file '{!s}'".format(self._filename)) + self.fail(f"Cannot read file '{self._filename}'") # Parse file = sem_lib.Load_File(sfe) @@ -54,7 +54,7 @@ class Instantiate(TestCase): self.assertEqual( "counter", entityName, - "expected entity name 'counter', got '{}'".format(entityName), + f"expected entity name 'counter', got '{entityName}'", ) elif nodes.Get_Kind(libraryUnit) == nodes.Iir_Kind.Architecture_Body: @@ -62,9 +62,7 @@ class Instantiate(TestCase): self.assertEqual( "rtl", architectureName, - "expected architecture name 'rtl', got '{}'".format( - architectureName - ), + f"expected architecture name 'rtl', got '{architectureName}'" ) else: -- cgit v1.2.3 From e7c771c8582f882ca2276b1d864c355c41eee4de Mon Sep 17 00:00:00 2001 From: Patrick Lehmann Date: Sat, 3 Dec 2022 22:16:08 +0100 Subject: Disable PIP version checks. --- .github/workflows/Test.yml | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/.github/workflows/Test.yml b/.github/workflows/Test.yml index 70b0bb8b5..03e8935de 100644 --- a/.github/workflows/Test.yml +++ b/.github/workflows/Test.yml @@ -101,8 +101,7 @@ jobs: run: | sudo apt update -qq sudo apt install -y gnat - python -m pip install --upgrade pip - python -m pip install black wheel pyTooling + python -m pip install --disable-pip-version-check black wheel pyTooling - name: '🚧 Update Python bindings' run: ./scripts/update_py_bindings.sh @@ -583,9 +582,8 @@ jobs: - name: '🐍 Install pyGHDL' run: | - python -m pip install --upgrade pip - python -m pip install wheel (& ls *.whl) - python -m pip install -r testsuite/requirements.txt + python -m pip install --disable-pip-version-check wheel (& ls *.whl) + python -m pip install --disable-pip-version-check -r testsuite/requirements.txt - name: '🚦 Test pyGHDL entrypoints' run: | @@ -692,7 +690,7 @@ jobs: - name: '🛠 Install package and 🐍 Python dependencies' run: | pacman --noconfirm -U artifact/mingw-w64-*-ghdl-llvm-*.zst - pip3 install -r testsuite/requirements.txt + pip3 install --disable-pip-version-check -r testsuite/requirements.txt - name: '🚦 Run tests to generate coverage report' run: PYTHONPATH=$(pwd) python3 -m pytest -rA --cov=.. --cov-config=.coveragerc testsuite/pyunit -- cgit v1.2.3 From b48f4c44f7a75cb0dadff20295bd2b9418f1d51b Mon Sep 17 00:00:00 2001 From: Patrick Lehmann Date: Sat, 3 Dec 2022 22:17:44 +0100 Subject: Adjusted to latest pyVHDLModel. --- pyGHDL/dom/Type.py | 17 +++++++++++------ pyGHDL/dom/_Translate.py | 1 - pyGHDL/dom/formatting/prettyprint.py | 6 +++--- pyGHDL/dom/requirements.txt | 2 +- 4 files changed, 15 insertions(+), 11 deletions(-) diff --git a/pyGHDL/dom/Type.py b/pyGHDL/dom/Type.py index 555a4b1ae..13362fdd6 100644 --- a/pyGHDL/dom/Type.py +++ b/pyGHDL/dom/Type.py @@ -30,7 +30,7 @@ # # SPDX-License-Identifier: GPL-2.0-or-later # ============================================================================ -from typing import List, Union, Iterator, Tuple +from typing import List, Union, Iterator, Tuple, Iterable from pyTooling.Decorators import export @@ -185,14 +185,18 @@ class RecordTypeElement(VHDLModel_RecordTypeElement, DOMMixin): DOMMixin.__init__(self, node) @classmethod - def parse(cls, elementDeclarationNode: Iir) -> "RecordTypeElement": + def parse(cls, elementDeclarationNode: Iir, furtherIdentifiers: Iterable[str] = None) -> "RecordTypeElement": from pyGHDL.dom._Utils import GetNameOfNode from pyGHDL.dom._Translate import GetSubtypeIndicationFromNode elementName = GetNameOfNode(elementDeclarationNode) elementType = GetSubtypeIndicationFromNode(elementDeclarationNode, "record element", elementName) - return cls(elementDeclarationNode, [elementName], elementType,) + identifiers = [elementName] + if furtherIdentifiers is not None: + identifiers.extend(furtherIdentifiers) + + return cls(elementDeclarationNode, identifiers, elementType,) @export @@ -208,13 +212,12 @@ class RecordType(VHDLModel_RecordType, DOMMixin): elements = [] elementDeclarations = nodes.Get_Elements_Declaration_List(typeDefinitionNode) + furtherIdentifiers = [] elementCount = flists.Flast(elementDeclarations) + 1 index = 0 while index < elementCount: elementDeclaration = flists.Get_Nth_Element(elementDeclarations, index) - element = RecordTypeElement.parse(elementDeclaration) - # Lookahead for elements with multiple identifiers at once if nodes.Get_Has_Identifier_List(elementDeclaration): index += 1 @@ -222,7 +225,7 @@ class RecordType(VHDLModel_RecordType, DOMMixin): nextNode: Iir = flists.Get_Nth_Element(elementDeclarations, index) # Consecutive identifiers are found, if the subtype indication is Null if nodes.Get_Subtype_Indication(nextNode) == nodes.Null_Iir: - element.Identifiers.append(GetNameOfNode(nextNode)) + furtherIdentifiers.append(GetNameOfNode(nextNode)) else: break index += 1 @@ -233,7 +236,9 @@ class RecordType(VHDLModel_RecordType, DOMMixin): else: index += 1 + element = RecordTypeElement.parse(elementDeclaration, furtherIdentifiers) elements.append(element) + furtherIdentifiers.clear() return cls(typeDefinitionNode, typeName, elements) diff --git a/pyGHDL/dom/_Translate.py b/pyGHDL/dom/_Translate.py index a125abfe5..788f0abbd 100644 --- a/pyGHDL/dom/_Translate.py +++ b/pyGHDL/dom/_Translate.py @@ -658,7 +658,6 @@ def GetDeclaredItemsFromChainedNodes(nodeChain: Iir, entity: str, name: str) -> from pyGHDL.dom.Object import Constant obj = Constant.parse(item) - elif kind == nodes.Iir_Kind.Variable_Declaration: from pyGHDL.dom.Object import SharedVariable diff --git a/pyGHDL/dom/formatting/prettyprint.py b/pyGHDL/dom/formatting/prettyprint.py index aa9c90c34..b5397610a 100644 --- a/pyGHDL/dom/formatting/prettyprint.py +++ b/pyGHDL/dom/formatting/prettyprint.py @@ -47,7 +47,7 @@ from pyGHDL.dom.Concurrent import ( ) from pyVHDLModel.SyntaxModel import ( GenericInterfaceItem, - NamedEntity, + NamedEntityMixin, PortInterfaceItem, WithDefaultExpressionMixin, Function, @@ -301,7 +301,7 @@ class PrettyPrint: return buffer - def formatGeneric(self, generic: Union[NamedEntity, GenericInterfaceItem], level: int = 0) -> StringBuffer: + def formatGeneric(self, generic: Union[NamedEntityMixin, GenericInterfaceItem], level: int = 0) -> StringBuffer: if isinstance(generic, GenericConstantInterfaceItem): return self.formatGenericConstant(generic, level) elif isinstance(generic, GenericTypeInterfaceItem): @@ -311,7 +311,7 @@ class PrettyPrint: f"Unhandled generic kind '{generic.__class__.__name__}' for generic '{generic.Identifiers[0]}'." ) - def formatPort(self, port: Union[NamedEntity, PortInterfaceItem], level: int = 0) -> StringBuffer: + def formatPort(self, port: Union[NamedEntityMixin, PortInterfaceItem], level: int = 0) -> StringBuffer: if isinstance(port, PortSignalInterfaceItem): return self.formatPortSignal(port, level) else: diff --git a/pyGHDL/dom/requirements.txt b/pyGHDL/dom/requirements.txt index 943757e92..09969e402 100644 --- a/pyGHDL/dom/requirements.txt +++ b/pyGHDL/dom/requirements.txt @@ -1,4 +1,4 @@ -r ../libghdl/requirements.txt -pyVHDLModel==0.14.4 +pyVHDLModel==0.16.0 #https://github.com/VHDL/pyVHDLModel/archive/dev.zip#pyVHDLModel -- cgit v1.2.3 From 5823ef28acc87cfbfc655b7e57a933ce1aca7a3c Mon Sep 17 00:00:00 2001 From: Patrick Lehmann Date: Sat, 3 Dec 2022 22:44:50 +0100 Subject: Fixed handling of multiple defined identifiers for latest pyVHDLModel. --- pyGHDL/dom/Object.py | 46 ++++++++++++++++++++++++++++++++-------------- pyGHDL/dom/_Translate.py | 21 ++++++++++++++------- 2 files changed, 46 insertions(+), 21 deletions(-) diff --git a/pyGHDL/dom/Object.py b/pyGHDL/dom/Object.py index 162bc8bef..1cf92179d 100644 --- a/pyGHDL/dom/Object.py +++ b/pyGHDL/dom/Object.py @@ -30,7 +30,7 @@ # # SPDX-License-Identifier: GPL-2.0-or-later # ============================================================================ -from typing import Union, List +from typing import Union, List, Iterable from pyTooling.Decorators import export @@ -67,22 +67,25 @@ class Constant(VHDLModel_Constant, DOMMixin): DOMMixin.__init__(self, node) @classmethod - def parse(cls, constantNode: Iir) -> Union["Constant", "DeferredConstant"]: + def parse(cls, constantNode: Iir, furtherIdentifiers: Iterable[str] = None) -> Union["Constant", "DeferredConstant"]: from pyGHDL.dom._Translate import ( GetSubtypeIndicationFromNode, GetExpressionFromNode, ) name = GetNameOfNode(constantNode) + identifiers = [name] + if furtherIdentifiers is not None: + identifiers.extend(furtherIdentifiers) documentation = GetDocumentationOfNode(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, documentation) + return cls(constantNode, identifiers, subtypeIndication, defaultExpression, documentation) else: - return DeferredConstant(constantNode, [name], subtypeIndication, documentation) + return DeferredConstant(constantNode, identifiers, subtypeIndication, documentation) @export @@ -92,14 +95,17 @@ class DeferredConstant(VHDLModel_DeferredConstant, DOMMixin): DOMMixin.__init__(self, node) @classmethod - def parse(cls, constantNode: Iir) -> "DeferredConstant": + def parse(cls, constantNode: Iir, furtherIdentifiers: Iterable[str] = None) -> "DeferredConstant": from pyGHDL.dom._Translate import GetSubtypeIndicationFromNode name = GetNameOfNode(constantNode) + identifiers = [name] + if furtherIdentifiers is not None: + identifiers.extend(furtherIdentifiers) documentation = GetDocumentationOfNode(constantNode) subtypeIndication = GetSubtypeIndicationFromNode(constantNode, "deferred constant", name) - return cls(constantNode, [name], subtypeIndication, documentation) + return cls(constantNode, identifiers, subtypeIndication, documentation) @export @@ -116,13 +122,16 @@ class Variable(VHDLModel_Variable, DOMMixin): DOMMixin.__init__(self, node) @classmethod - def parse(cls, variableNode: Iir) -> "Variable": + def parse(cls, variableNode: Iir, furtherIdentifiers: Iterable[str] = None) -> "Variable": from pyGHDL.dom._Translate import ( GetSubtypeIndicationFromNode, GetExpressionFromNode, ) name = GetNameOfNode(variableNode) + identifiers = [name] + if furtherIdentifiers is not None: + identifiers.extend(furtherIdentifiers) documentation = GetDocumentationOfNode(variableNode) subtypeIndication = GetSubtypeIndicationFromNode(variableNode, "variable", name) defaultValue = nodes.Get_Default_Value(variableNode) @@ -130,7 +139,7 @@ class Variable(VHDLModel_Variable, DOMMixin): if defaultValue != nodes.Null_Iir: defaultExpression = GetExpressionFromNode(defaultValue) - return cls(variableNode, [name], subtypeIndication, defaultExpression, documentation) + return cls(variableNode, identifiers, subtypeIndication, defaultExpression, documentation) @export @@ -140,14 +149,17 @@ class SharedVariable(VHDLModel_SharedVariable, DOMMixin): DOMMixin.__init__(self, node) @classmethod - def parse(cls, variableNode: Iir) -> "SharedVariable": + def parse(cls, variableNode: Iir, furtherIdentifiers: Iterable[str] = None) -> "SharedVariable": from pyGHDL.dom._Translate import GetSubtypeIndicationFromNode name = GetNameOfNode(variableNode) + identifiers = [name] + if furtherIdentifiers is not None: + identifiers.extend(furtherIdentifiers) documentation = GetDocumentationOfNode(variableNode) subtypeIndication = GetSubtypeIndicationFromNode(variableNode, "variable", name) - return cls(variableNode, [name], subtypeIndication, documentation) + return cls(variableNode, identifiers, subtypeIndication, documentation) @export @@ -164,19 +176,22 @@ class Signal(VHDLModel_Signal, DOMMixin): DOMMixin.__init__(self, node) @classmethod - def parse(cls, signalNode: Iir) -> "Signal": + def parse(cls, signalNode: Iir, furtherIdentifiers: Iterable[str] = None) -> "Signal": from pyGHDL.dom._Translate import ( GetSubtypeIndicationFromNode, GetExpressionFromNode, ) name = GetNameOfNode(signalNode) + identifiers = [name] + if furtherIdentifiers is not None: + identifiers.extend(furtherIdentifiers) documentation = GetDocumentationOfNode(signalNode) subtypeIndication = GetSubtypeIndicationFromNode(signalNode, "signal", name) default = nodes.Get_Default_Value(signalNode) defaultExpression = GetExpressionFromNode(default) if default else None - return cls(signalNode, [name], subtypeIndication, defaultExpression, documentation) + return cls(signalNode, identifiers, subtypeIndication, defaultExpression, documentation) @export @@ -186,13 +201,16 @@ class File(VHDLModel_File, DOMMixin): DOMMixin.__init__(self, node) @classmethod - def parse(cls, fileNode: Iir) -> "File": + def parse(cls, fileNode: Iir, furtherIdentifiers: Iterable[str] = None) -> "File": from pyGHDL.dom._Translate import GetSubtypeIndicationFromNode name = GetNameOfNode(fileNode) + identifiers = [name] + if furtherIdentifiers is not None: + identifiers.extend(furtherIdentifiers) documentation = GetDocumentationOfNode(fileNode) subtypeIndication = GetSubtypeIndicationFromNode(fileNode, "file", name) # FIXME: handle file open stuff - return cls(fileNode, [name], subtypeIndication, documentation) + return cls(fileNode, identifiers, subtypeIndication, documentation) diff --git a/pyGHDL/dom/_Translate.py b/pyGHDL/dom/_Translate.py index 788f0abbd..ef8656e52 100644 --- a/pyGHDL/dom/_Translate.py +++ b/pyGHDL/dom/_Translate.py @@ -650,6 +650,7 @@ def GetParameterMapAspect( def GetDeclaredItemsFromChainedNodes(nodeChain: Iir, entity: str, name: str) -> Generator[ModelEntity, None, None]: + furtherIdentifiers = [] item = nodeChain lastKind = None while item != nodes.Null_Iir: @@ -657,22 +658,27 @@ def GetDeclaredItemsFromChainedNodes(nodeChain: Iir, entity: str, name: str) -> if kind == nodes.Iir_Kind.Constant_Declaration: from pyGHDL.dom.Object import Constant - obj = Constant.parse(item) + objectParseMethod = Constant.parse + objectItem = item elif kind == nodes.Iir_Kind.Variable_Declaration: from pyGHDL.dom.Object import SharedVariable if nodes.Get_Shared_Flag(item): - obj = SharedVariable.parse(item) + objectParseMethod = SharedVariable.parse + objectItem = item else: - obj = Variable.parse(item) + objectParseMethod = Variable.parse + objectItem = item elif kind == nodes.Iir_Kind.Signal_Declaration: from pyGHDL.dom.Object import Signal - obj = Signal.parse(item) + objectParseMethod = Signal.parse + objectItem = item elif kind == nodes.Iir_Kind.File_Declaration: from pyGHDL.dom.Object import File - obj = File.parse(item) + objectParseMethod = File.parse + objectItem = item else: if kind == nodes.Iir_Kind.Type_Declaration: yield GetTypeFromNode(item) @@ -781,7 +787,7 @@ def GetDeclaredItemsFromChainedNodes(nodeChain: Iir, entity: str, name: str) -> for nextItem in utils.chain_iter(nextNode): # Consecutive identifiers are found, if the subtype indication is Null if nodes.Get_Subtype_Indication(nextItem) == nodes.Null_Iir: - obj.Identifiers.append(GetNameOfNode(nextItem)) + furtherIdentifiers.append(GetNameOfNode(nextItem)) else: item = nextItem break @@ -795,7 +801,8 @@ def GetDeclaredItemsFromChainedNodes(nodeChain: Iir, entity: str, name: str) -> else: item = nodes.Get_Chain(item) - yield obj + yield objectParseMethod(objectItem, furtherIdentifiers) + furtherIdentifiers.clear() def GetConcurrentStatementsFromChainedNodes( -- cgit v1.2.3 From b32eea0036728b58735783d581df6b2a99fb6171 Mon Sep 17 00:00:00 2001 From: Patrick Lehmann Date: Sun, 4 Dec 2022 19:12:42 +0100 Subject: Reorganized comment tests. --- pyGHDL/dom/__init__.py | 2 -- testsuite/pyunit/dom/SimpleEntity.py | 17 +++++++++++++++-- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/pyGHDL/dom/__init__.py b/pyGHDL/dom/__init__.py index e9eb89240..12caccc1b 100644 --- a/pyGHDL/dom/__init__.py +++ b/pyGHDL/dom/__init__.py @@ -39,8 +39,6 @@ from pyGHDL.libghdl import files_map, name_table from pyGHDL.libghdl._types import Iir from pyGHDL.libghdl.vhdl import nodes -__all__ = [] - @export class Position: diff --git a/testsuite/pyunit/dom/SimpleEntity.py b/testsuite/pyunit/dom/SimpleEntity.py index 7e19c2d17..c2167c973 100644 --- a/testsuite/pyunit/dom/SimpleEntity.py +++ b/testsuite/pyunit/dom/SimpleEntity.py @@ -60,6 +60,9 @@ class SimpleEntity(TestCase): design.Documents.append(document) self.assertEqual(1, len(design.Documents)) + print() + print(document.Documentation) + self.assertEqual(4, len(document.Documentation.splitlines())) def test_Entity(self): design = Design() @@ -67,7 +70,12 @@ class SimpleEntity(TestCase): design.Documents.append(document) self.assertEqual(1, len(design.Documents[0].Entities)) - self.assertEqual("Counter", design.Documents[0].Entities[0].Identifier) + + entity = design.Documents[0].Entities[0] + self.assertEqual("Counter", entity.Identifier) + print() + print(entity.Documentation) + self.assertEqual(11, len(entity.Documentation.splitlines())) def test_Architecture(self): design = Design() @@ -75,4 +83,9 @@ class SimpleEntity(TestCase): design.Documents.append(document) self.assertEqual(1, len(design.Documents[0].Architectures)) - self.assertEqual("rtl", design.Documents[0].Architectures[0].Identifier) + + architecture = design.Documents[0].Architectures[0] + self.assertEqual("rtl", architecture.Identifier) + print() + print(architecture.Documentation) + self.assertEqual(1, len(architecture.Documentation.splitlines())) -- cgit v1.2.3 From 3f8b41a61936c55f073325f8b19b8340839595e9 Mon Sep 17 00:00:00 2001 From: Patrick Lehmann Date: Sun, 4 Dec 2022 19:13:26 +0100 Subject: Bumped version of pyVHDLModel to 0.17.1. --- pyGHDL/dom/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyGHDL/dom/requirements.txt b/pyGHDL/dom/requirements.txt index 09969e402..6e0c0259a 100644 --- a/pyGHDL/dom/requirements.txt +++ b/pyGHDL/dom/requirements.txt @@ -1,4 +1,4 @@ -r ../libghdl/requirements.txt -pyVHDLModel==0.16.0 +pyVHDLModel==0.17.1 #https://github.com/VHDL/pyVHDLModel/archive/dev.zip#pyVHDLModel -- cgit v1.2.3 From 75c3f850ce617b86fd1393d12638ebee32c516cc Mon Sep 17 00:00:00 2001 From: Patrick Lehmann Date: Tue, 6 Dec 2022 08:12:27 +0100 Subject: Here is blacks opinion. --- pyGHDL/dom/Attribute.py | 2 +- pyGHDL/dom/DesignUnit.py | 24 +++++++++-------------- pyGHDL/dom/InterfaceItem.py | 46 ++++++++++----------------------------------- pyGHDL/dom/Object.py | 10 ++++++---- pyGHDL/dom/Subprogram.py | 4 ++-- pyGHDL/dom/Type.py | 2 +- 6 files changed, 29 insertions(+), 59 deletions(-) diff --git a/pyGHDL/dom/Attribute.py b/pyGHDL/dom/Attribute.py index 576b05245..ccd3ecf47 100644 --- a/pyGHDL/dom/Attribute.py +++ b/pyGHDL/dom/Attribute.py @@ -103,7 +103,7 @@ class AttributeSpecification(VHDLModel_AttributeSpecification, DOMMixin): attribute: Name, entityClass: EntityClass, expression: Expression, - documentation: str = None + documentation: str = None, ): super().__init__(identifiers, attribute, entityClass, expression, documentation) DOMMixin.__init__(self, node) diff --git a/pyGHDL/dom/DesignUnit.py b/pyGHDL/dom/DesignUnit.py index 853184450..47eb8e766 100644 --- a/pyGHDL/dom/DesignUnit.py +++ b/pyGHDL/dom/DesignUnit.py @@ -132,7 +132,7 @@ class Entity(VHDLModel_Entity, DOMMixin): portItems: Iterable[PortInterfaceItem] = None, declaredItems: Iterable = None, statements: Iterable["ConcurrentStatement"] = None, - documentation: str = None + documentation: str = None, ): super().__init__(identifier, contextItems, genericItems, portItems, declaredItems, statements, documentation) DOMMixin.__init__(self, node) @@ -163,7 +163,7 @@ class Architecture(VHDLModel_Architecture, DOMMixin): contextItems: Iterable[ContextUnion] = None, declaredItems: Iterable = None, statements: Iterable["ConcurrentStatement"] = None, - documentation: str = None + documentation: str = None, ): super().__init__(identifier, entity, contextItems, declaredItems, statements, documentation) DOMMixin.__init__(self, node) @@ -195,7 +195,7 @@ class Component(VHDLModel_Component, DOMMixin): identifier: str, genericItems: Iterable[GenericInterfaceItem] = None, portItems: Iterable[PortInterfaceItem] = None, - documentation: str = None + documentation: str = None, ): super().__init__(identifier, genericItems, portItems, documentation) DOMMixin.__init__(self, node) @@ -219,7 +219,7 @@ class Package(VHDLModel_Package, DOMMixin): contextItems: Iterable[ContextUnion] = None, genericItems: Iterable[GenericInterfaceItem] = None, declaredItems: Iterable = None, - documentation: str = None + documentation: str = None, ): super().__init__(identifier, contextItems, genericItems, declaredItems, documentation) DOMMixin.__init__(self, node) @@ -250,7 +250,7 @@ class PackageBody(VHDLModel_PackageBody, DOMMixin): identifier: str, contextItems: Iterable[ContextUnion] = None, declaredItems: Iterable = None, - documentation: str = None + documentation: str = None, ): super().__init__(identifier, contextItems, declaredItems, documentation) DOMMixin.__init__(self, node) @@ -274,7 +274,7 @@ class PackageInstantiation(VHDLModel_PackageInstantiation, DOMMixin): identifier: str, uninstantiatedPackageName: Name, # genericItems: List[GenericInterfaceItem] = None, - documentation: str = None + documentation: str = None, ): super().__init__(identifier, uninstantiatedPackageName, documentation) DOMMixin.__init__(self, node) @@ -301,7 +301,7 @@ class Context(VHDLModel_Context, DOMMixin): identifier: str, libraryReferences: Iterable[LibraryClause] = None, packageReferences: Iterable[UseClause] = None, - documentation: str = None + documentation: str = None, ): super().__init__(identifier, libraryReferences, packageReferences, documentation) DOMMixin.__init__(self, node) @@ -335,19 +335,13 @@ class Context(VHDLModel_Context, DOMMixin): @export class Configuration(VHDLModel_Configuration, DOMMixin): - def __init__( - self, - node: Iir, - identifier: str, - contextItems: Iterable[Context] = None, - documentation: str = None - ): + def __init__(self, node: Iir, identifier: str, contextItems: Iterable[Context] = None, documentation: str = None): super().__init__(identifier, contextItems, documentation) DOMMixin.__init__(self, node) @classmethod def parse(cls, configurationNode: Iir, contextItems: Iterable[Context]): - name = GetNameOfNode(configurationNode), + name = (GetNameOfNode(configurationNode),) documentation = GetDocumentationOfNode(configurationNode) # FIXME: read use clauses diff --git a/pyGHDL/dom/InterfaceItem.py b/pyGHDL/dom/InterfaceItem.py index e42c8dcb2..fb8a1b320 100644 --- a/pyGHDL/dom/InterfaceItem.py +++ b/pyGHDL/dom/InterfaceItem.py @@ -69,7 +69,7 @@ class GenericConstantInterfaceItem(VHDLModel_GenericConstantInterfaceItem, DOMMi mode: Mode, subtype: SubtypeOrSymbol, defaultExpression: ExpressionUnion, - documentation: str = None + documentation: str = None, ): super().__init__(identifiers, mode, subtype, defaultExpression, documentation) DOMMixin.__init__(self, node) @@ -88,12 +88,7 @@ class GenericConstantInterfaceItem(VHDLModel_GenericConstantInterfaceItem, DOMMi @export class GenericTypeInterfaceItem(VHDLModel_GenericTypeInterfaceItem, DOMMixin): - def __init__( - self, - node: Iir, - identifier: str, - documentation: str = None - ): + def __init__(self, node: Iir, identifier: str, documentation: str = None): super().__init__(identifier, documentation) DOMMixin.__init__(self, node) @@ -107,12 +102,7 @@ class GenericTypeInterfaceItem(VHDLModel_GenericTypeInterfaceItem, DOMMixin): @export class GenericPackageInterfaceItem(VHDLModel_GenericPackageInterfaceItem, DOMMixin): - def __init__( - self, - node: Iir, - name: str, - documentation: str = None - ): + def __init__(self, node: Iir, name: str, documentation: str = None): super().__init__(name, documentation) DOMMixin.__init__(self, node) @@ -126,12 +116,7 @@ class GenericPackageInterfaceItem(VHDLModel_GenericPackageInterfaceItem, DOMMixi @export class GenericProcedureInterfaceItem(VHDLModel_GenericProcedureInterfaceItem, DOMMixin): - def __init__( - self, - node: Iir, - identifier: str, - documentation: str = None - ): + def __init__(self, node: Iir, identifier: str, documentation: str = None): super().__init__(identifier, documentation) DOMMixin.__init__(self, node) @@ -145,12 +130,7 @@ class GenericProcedureInterfaceItem(VHDLModel_GenericProcedureInterfaceItem, DOM @export class GenericFunctionInterfaceItem(VHDLModel_GenericFunctionInterfaceItem, DOMMixin): - def __init__( - self, - node: Iir, - identifier: str, - documentation: str = None - ): + def __init__(self, node: Iir, identifier: str, documentation: str = None): super().__init__(identifier, documentation) DOMMixin.__init__(self, node) @@ -171,7 +151,7 @@ class PortSignalInterfaceItem(VHDLModel_PortSignalInterfaceItem, DOMMixin): mode: Mode, subtype: SubtypeOrSymbol, defaultExpression: ExpressionUnion = None, - documentation: str = None + documentation: str = None, ): super().__init__(identifiers, mode, subtype, defaultExpression, documentation) DOMMixin.__init__(self, node) @@ -198,7 +178,7 @@ class ParameterConstantInterfaceItem(VHDLModel_ParameterConstantInterfaceItem, D mode: Mode, subtype: SubtypeOrSymbol, defaultExpression: ExpressionUnion = None, - documentation: str = None + documentation: str = None, ): super().__init__(identifiers, mode, subtype, defaultExpression, documentation) DOMMixin.__init__(self, node) @@ -225,7 +205,7 @@ class ParameterVariableInterfaceItem(VHDLModel_ParameterVariableInterfaceItem, D mode: Mode, subtype: SubtypeOrSymbol, defaultExpression: ExpressionUnion = None, - documentation: str = None + documentation: str = None, ): super().__init__(identifiers, mode, subtype, defaultExpression, documentation) DOMMixin.__init__(self, node) @@ -252,7 +232,7 @@ class ParameterSignalInterfaceItem(VHDLModel_ParameterSignalInterfaceItem, DOMMi mode: Mode, subtype: SubtypeOrSymbol, defaultExpression: ExpressionUnion = None, - documentation: str = None + documentation: str = None, ): super().__init__(identifiers, mode, subtype, defaultExpression, documentation) DOMMixin.__init__(self, node) @@ -272,13 +252,7 @@ class ParameterSignalInterfaceItem(VHDLModel_ParameterSignalInterfaceItem, DOMMi @export class ParameterFileInterfaceItem(VHDLModel_ParameterFileInterfaceItem, DOMMixin): - def __init__( - self, - node: Iir, - identifiers: List[str], - subtype: SubtypeOrSymbol, - documentation: str = None - ): + def __init__(self, node: Iir, identifiers: List[str], subtype: SubtypeOrSymbol, documentation: str = None): super().__init__(identifiers, subtype, documentation) DOMMixin.__init__(self, node) diff --git a/pyGHDL/dom/Object.py b/pyGHDL/dom/Object.py index 1cf92179d..e3528c9db 100644 --- a/pyGHDL/dom/Object.py +++ b/pyGHDL/dom/Object.py @@ -61,13 +61,15 @@ class Constant(VHDLModel_Constant, DOMMixin): identifiers: List[str], subtype: SubtypeOrSymbol, defaultExpression: ExpressionUnion, - documentation: str = None + documentation: str = None, ): super().__init__(identifiers, subtype, defaultExpression, documentation) DOMMixin.__init__(self, node) @classmethod - def parse(cls, constantNode: Iir, furtherIdentifiers: Iterable[str] = None) -> Union["Constant", "DeferredConstant"]: + def parse( + cls, constantNode: Iir, furtherIdentifiers: Iterable[str] = None + ) -> Union["Constant", "DeferredConstant"]: from pyGHDL.dom._Translate import ( GetSubtypeIndicationFromNode, GetExpressionFromNode, @@ -116,7 +118,7 @@ class Variable(VHDLModel_Variable, DOMMixin): identifiers: List[str], subtype: SubtypeOrSymbol, defaultExpression: ExpressionUnion, - documentation: str = None + documentation: str = None, ): super().__init__(identifiers, subtype, defaultExpression, documentation) DOMMixin.__init__(self, node) @@ -170,7 +172,7 @@ class Signal(VHDLModel_Signal, DOMMixin): identifiers: List[str], subtype: SubtypeOrSymbol, defaultExpression: ExpressionUnion, - documentation: str = None + documentation: str = None, ): super().__init__(identifiers, subtype, defaultExpression, documentation) DOMMixin.__init__(self, node) diff --git a/pyGHDL/dom/Subprogram.py b/pyGHDL/dom/Subprogram.py index ba7ee035a..46ce92707 100644 --- a/pyGHDL/dom/Subprogram.py +++ b/pyGHDL/dom/Subprogram.py @@ -57,7 +57,7 @@ class Function(VHDLModel_Function, DOMMixin): returnType: SubtypeOrSymbol, genericItems: List[GenericInterfaceItem] = None, parameterItems: List[ParameterInterfaceItem] = None, - documentation: str = None + documentation: str = None, ): super().__init__(functionName, documentation) DOMMixin.__init__(self, node) @@ -95,7 +95,7 @@ class Procedure(VHDLModel_Procedure, DOMMixin): procedureName: str, genericItems: List[GenericInterfaceItem] = None, parameterItems: List[ParameterInterfaceItem] = None, - documentation: str = None + documentation: str = None, ): super().__init__(procedureName, documentation) DOMMixin.__init__(self, node) diff --git a/pyGHDL/dom/Type.py b/pyGHDL/dom/Type.py index 13362fdd6..2b71ccc3c 100644 --- a/pyGHDL/dom/Type.py +++ b/pyGHDL/dom/Type.py @@ -196,7 +196,7 @@ class RecordTypeElement(VHDLModel_RecordTypeElement, DOMMixin): if furtherIdentifiers is not None: identifiers.extend(furtherIdentifiers) - return cls(elementDeclarationNode, identifiers, elementType,) + return cls(elementDeclarationNode, identifiers, elementType) @export -- cgit v1.2.3 From d557b50e78e74801bf296b18a004a468555921be Mon Sep 17 00:00:00 2001 From: Patrick Lehmann Date: Tue, 6 Dec 2022 00:36:29 +0100 Subject: Updated for latest pyVHDLModel v0.17.x (cherry picked from commit fb6e98b119cc1bb94ba5ecca88d7533a00a2e3f6) --- pyGHDL/dom/InterfaceItem.py | 44 +++++++++++++++++++++++++++++++------------- pyGHDL/dom/Object.py | 12 ++++++------ pyGHDL/dom/_Translate.py | 33 ++++++++++++++++++++------------- 3 files changed, 57 insertions(+), 32 deletions(-) diff --git a/pyGHDL/dom/InterfaceItem.py b/pyGHDL/dom/InterfaceItem.py index fb8a1b320..aa63f3094 100644 --- a/pyGHDL/dom/InterfaceItem.py +++ b/pyGHDL/dom/InterfaceItem.py @@ -30,7 +30,7 @@ # # SPDX-License-Identifier: GPL-2.0-or-later # ============================================================================ -from typing import List +from typing import List, Iterable from pyTooling.Decorators import export @@ -75,15 +75,18 @@ class GenericConstantInterfaceItem(VHDLModel_GenericConstantInterfaceItem, DOMMi DOMMixin.__init__(self, node) @classmethod - def parse(cls, genericNode: Iir) -> "GenericConstantInterfaceItem": + def parse(cls, genericNode: Iir, furtherIdentifiers: Iterable[str] = None) -> "GenericConstantInterfaceItem": name = GetNameOfNode(genericNode) documentation = GetDocumentationOfNode(genericNode) + identifiers = [name] + if furtherIdentifiers is not None: + identifiers.extend(furtherIdentifiers) mode = GetModeOfNode(genericNode) subtypeIndication = GetSubtypeIndicationFromNode(genericNode, "generic", name) default = nodes.Get_Default_Value(genericNode) value = GetExpressionFromNode(default) if default else None - return cls(genericNode, [name], mode, subtypeIndication, value, documentation) + return cls(genericNode, identifiers, mode, subtypeIndication, value, documentation) @export @@ -157,16 +160,19 @@ class PortSignalInterfaceItem(VHDLModel_PortSignalInterfaceItem, DOMMixin): DOMMixin.__init__(self, node) @classmethod - def parse(cls, portNode: Iir) -> "PortSignalInterfaceItem": + def parse(cls, portNode: Iir, furtherIdentifiers: Iterable[str] = None) -> "PortSignalInterfaceItem": name = GetNameOfNode(portNode) documentation = GetDocumentationOfNode(portNode) + identifiers = [name] + if furtherIdentifiers is not None: + identifiers.extend(furtherIdentifiers) mode = GetModeOfNode(portNode) subtypeIndication = GetSubtypeIndicationFromNode(portNode, "port", name) defaultValue = nodes.Get_Default_Value(portNode) value = GetExpressionFromNode(defaultValue) if defaultValue != nodes.Null_Iir else None - return cls(portNode, [name], mode, subtypeIndication, value, documentation) + return cls(portNode, identifiers, mode, subtypeIndication, value, documentation) @export @@ -184,16 +190,19 @@ class ParameterConstantInterfaceItem(VHDLModel_ParameterConstantInterfaceItem, D DOMMixin.__init__(self, node) @classmethod - def parse(cls, parameterNode: Iir) -> "ParameterConstantInterfaceItem": + def parse(cls, parameterNode: Iir, furtherIdentifiers: Iterable[str] = None) -> "ParameterConstantInterfaceItem": name = GetNameOfNode(parameterNode) documentation = GetDocumentationOfNode(parameterNode) + identifiers = [name] + if furtherIdentifiers is not None: + identifiers.extend(furtherIdentifiers) mode = GetModeOfNode(parameterNode) subtypeIndication = GetSubtypeIndicationFromNode(parameterNode, "parameter", name) defaultValue = nodes.Get_Default_Value(parameterNode) value = GetExpressionFromNode(defaultValue) if defaultValue != nodes.Null_Iir else None - return cls(parameterNode, [name], mode, subtypeIndication, value, documentation) + return cls(parameterNode, identifiers, mode, subtypeIndication, value, documentation) @export @@ -211,16 +220,19 @@ class ParameterVariableInterfaceItem(VHDLModel_ParameterVariableInterfaceItem, D DOMMixin.__init__(self, node) @classmethod - def parse(cls, parameterNode: Iir) -> "ParameterVariableInterfaceItem": + def parse(cls, parameterNode: Iir, furtherIdentifiers: Iterable[str] = None) -> "ParameterVariableInterfaceItem": name = GetNameOfNode(parameterNode) documentation = GetDocumentationOfNode(parameterNode) + identifiers = [name] + if furtherIdentifiers is not None: + identifiers.extend(furtherIdentifiers) mode = GetModeOfNode(parameterNode) subtypeIndication = GetSubtypeIndicationFromNode(parameterNode, "parameter", name) defaultValue = nodes.Get_Default_Value(parameterNode) value = GetExpressionFromNode(defaultValue) if defaultValue != nodes.Null_Iir else None - return cls(parameterNode, [name], mode, subtypeIndication, value, documentation) + return cls(parameterNode, identifiers, mode, subtypeIndication, value, documentation) @export @@ -238,16 +250,19 @@ class ParameterSignalInterfaceItem(VHDLModel_ParameterSignalInterfaceItem, DOMMi DOMMixin.__init__(self, node) @classmethod - def parse(cls, parameterNode: Iir) -> "ParameterSignalInterfaceItem": + def parse(cls, parameterNode: Iir, furtherIdentifiers: Iterable[str] = None) -> "ParameterSignalInterfaceItem": name = GetNameOfNode(parameterNode) documentation = GetDocumentationOfNode(parameterNode) + identifiers = [name] + if furtherIdentifiers is not None: + identifiers.extend(furtherIdentifiers) mode = GetModeOfNode(parameterNode) subtypeIndication = GetSubtypeIndicationFromNode(parameterNode, "parameter", name) defaultValue = nodes.Get_Default_Value(parameterNode) value = GetExpressionFromNode(defaultValue) if defaultValue != nodes.Null_Iir else None - return cls(parameterNode, [name], mode, subtypeIndication, value, documentation) + return cls(parameterNode, identifiers, mode, subtypeIndication, value, documentation) @export @@ -257,9 +272,12 @@ class ParameterFileInterfaceItem(VHDLModel_ParameterFileInterfaceItem, DOMMixin) DOMMixin.__init__(self, node) @classmethod - def parse(cls, parameterNode: Iir) -> "ParameterFileInterfaceItem": + def parse(cls, parameterNode: Iir, furtherIdentifiers: Iterable[str] = None) -> "ParameterFileInterfaceItem": name = GetNameOfNode(parameterNode) documentation = GetDocumentationOfNode(parameterNode) + identifiers = [name] + if furtherIdentifiers is not None: + identifiers.extend(furtherIdentifiers) subtypeIndication = GetSubtypeIndicationFromNode(parameterNode, "parameter", name) - return cls(parameterNode, [name], subtypeIndication, documentation) + return cls(parameterNode, identifiers, subtypeIndication, documentation) diff --git a/pyGHDL/dom/Object.py b/pyGHDL/dom/Object.py index e3528c9db..1079eae4a 100644 --- a/pyGHDL/dom/Object.py +++ b/pyGHDL/dom/Object.py @@ -76,10 +76,10 @@ class Constant(VHDLModel_Constant, DOMMixin): ) name = GetNameOfNode(constantNode) + documentation = GetDocumentationOfNode(constantNode) identifiers = [name] if furtherIdentifiers is not None: identifiers.extend(furtherIdentifiers) - documentation = GetDocumentationOfNode(constantNode) subtypeIndication = GetSubtypeIndicationFromNode(constantNode, "constant", name) defaultValue = nodes.Get_Default_Value(constantNode) if defaultValue != nodes.Null_Iir: @@ -101,10 +101,10 @@ class DeferredConstant(VHDLModel_DeferredConstant, DOMMixin): from pyGHDL.dom._Translate import GetSubtypeIndicationFromNode name = GetNameOfNode(constantNode) + documentation = GetDocumentationOfNode(constantNode) identifiers = [name] if furtherIdentifiers is not None: identifiers.extend(furtherIdentifiers) - documentation = GetDocumentationOfNode(constantNode) subtypeIndication = GetSubtypeIndicationFromNode(constantNode, "deferred constant", name) return cls(constantNode, identifiers, subtypeIndication, documentation) @@ -131,10 +131,10 @@ class Variable(VHDLModel_Variable, DOMMixin): ) name = GetNameOfNode(variableNode) + documentation = GetDocumentationOfNode(variableNode) identifiers = [name] if furtherIdentifiers is not None: identifiers.extend(furtherIdentifiers) - documentation = GetDocumentationOfNode(variableNode) subtypeIndication = GetSubtypeIndicationFromNode(variableNode, "variable", name) defaultValue = nodes.Get_Default_Value(variableNode) defaultExpression = None @@ -155,10 +155,10 @@ class SharedVariable(VHDLModel_SharedVariable, DOMMixin): from pyGHDL.dom._Translate import GetSubtypeIndicationFromNode name = GetNameOfNode(variableNode) + documentation = GetDocumentationOfNode(variableNode) identifiers = [name] if furtherIdentifiers is not None: identifiers.extend(furtherIdentifiers) - documentation = GetDocumentationOfNode(variableNode) subtypeIndication = GetSubtypeIndicationFromNode(variableNode, "variable", name) return cls(variableNode, identifiers, subtypeIndication, documentation) @@ -185,10 +185,10 @@ class Signal(VHDLModel_Signal, DOMMixin): ) name = GetNameOfNode(signalNode) + documentation = GetDocumentationOfNode(signalNode) identifiers = [name] if furtherIdentifiers is not None: identifiers.extend(furtherIdentifiers) - documentation = GetDocumentationOfNode(signalNode) subtypeIndication = GetSubtypeIndicationFromNode(signalNode, "signal", name) default = nodes.Get_Default_Value(signalNode) defaultExpression = GetExpressionFromNode(default) if default else None @@ -207,10 +207,10 @@ class File(VHDLModel_File, DOMMixin): from pyGHDL.dom._Translate import GetSubtypeIndicationFromNode name = GetNameOfNode(fileNode) + documentation = GetDocumentationOfNode(fileNode) identifiers = [name] if furtherIdentifiers is not None: identifiers.extend(furtherIdentifiers) - documentation = GetDocumentationOfNode(fileNode) subtypeIndication = GetSubtypeIndicationFromNode(fileNode, "file", name) # FIXME: handle file open stuff diff --git a/pyGHDL/dom/_Translate.py b/pyGHDL/dom/_Translate.py index ef8656e52..d39b14765 100644 --- a/pyGHDL/dom/_Translate.py +++ b/pyGHDL/dom/_Translate.py @@ -464,21 +464,20 @@ def GetGenericsFromChainedNodes( GenericFunctionInterfaceItem, ) + furtherIdentifiers = [] generic = nodeChain while generic != nodes.Null_Iir: kind = GetIirKindOfNode(generic) if kind == nodes.Iir_Kind.Interface_Constant_Declaration: from pyGHDL.dom.InterfaceItem import GenericConstantInterfaceItem - genericConstant = GenericConstantInterfaceItem.parse(generic) - # Lookahead for generics with multiple identifiers at once if nodes.Get_Has_Identifier_List(generic): nextNode = nodes.Get_Chain(generic) for nextGeneric in utils.chain_iter(nextNode): # Consecutive identifiers are found, if the subtype indication is Null if nodes.Get_Subtype_Indication(nextGeneric) == nodes.Null_Iir: - genericConstant.Identifiers.append(GetNameOfNode(nextGeneric)) + furtherIdentifiers.append(GetNameOfNode(nextGeneric)) else: generic = nextGeneric break @@ -492,7 +491,8 @@ def GetGenericsFromChainedNodes( else: generic = nodes.Get_Chain(generic) - yield genericConstant + yield GenericConstantInterfaceItem.parse(generic, furtherIdentifiers) + furtherIdentifiers.clear() continue else: if kind == nodes.Iir_Kind.Interface_Type_Declaration: @@ -517,13 +517,14 @@ def GetPortsFromChainedNodes( nodeChain: Iir, ) -> Generator[PortInterfaceItem, None, None]: + furtherIdentifiers = [] port = nodeChain while port != nodes.Null_Iir: kind = GetIirKindOfNode(port) if kind == nodes.Iir_Kind.Interface_Signal_Declaration: from pyGHDL.dom.InterfaceItem import PortSignalInterfaceItem - portSignal = PortSignalInterfaceItem.parse(port) + portToParse = port # Lookahead for ports with multiple identifiers at once if nodes.Get_Has_Identifier_List(port): @@ -531,7 +532,7 @@ def GetPortsFromChainedNodes( for nextPort in utils.chain_iter(nextNode): # Consecutive identifiers are found, if the subtype indication is Null if nodes.Get_Subtype_Indication(nextPort) == nodes.Null_Iir: - portSignal.Identifiers.append(GetNameOfNode(nextPort)) + furtherIdentifiers.append(GetNameOfNode(nextPort)) else: port = nextPort break @@ -545,7 +546,8 @@ def GetPortsFromChainedNodes( else: port = nodes.Get_Chain(port) - yield portSignal + yield PortSignalInterfaceItem.parse(portToParse, furtherIdentifiers) + furtherIdentifiers.clear() continue else: position = Position.parse(port) @@ -559,25 +561,30 @@ def GetParameterFromChainedNodes( nodeChain: Iir, ) -> Generator[ParameterInterfaceItem, None, None]: + identifiers = [] parameter = nodeChain while parameter != nodes.Null_Iir: kind = GetIirKindOfNode(parameter) if kind == nodes.Iir_Kind.Interface_Constant_Declaration: from pyGHDL.dom.InterfaceItem import ParameterConstantInterfaceItem - param = ParameterConstantInterfaceItem.parse(parameter) + parseMethod = ParameterConstantInterfaceItem.parse + parseNode = parameter elif kind == nodes.Iir_Kind.Interface_Variable_Declaration: from pyGHDL.dom.InterfaceItem import ParameterVariableInterfaceItem - param = ParameterVariableInterfaceItem.parse(parameter) + parseMethod = ParameterVariableInterfaceItem.parse + parseNode = parameter elif kind == nodes.Iir_Kind.Interface_Signal_Declaration: from pyGHDL.dom.InterfaceItem import ParameterSignalInterfaceItem - param = ParameterSignalInterfaceItem.parse(parameter) + parseMethod = ParameterSignalInterfaceItem.parse + parseNode = parameter elif kind == nodes.Iir_Kind.Interface_File_Declaration: from pyGHDL.dom.InterfaceItem import ParameterFileInterfaceItem - param = ParameterFileInterfaceItem.parse(parameter) + parseMethod = ParameterFileInterfaceItem.parse + parseNode = parameter else: position = Position.parse(parameter) raise DOMException( @@ -590,7 +597,7 @@ def GetParameterFromChainedNodes( for nextParameter in utils.chain_iter(nextNode): # Consecutive identifiers are found, if the subtype indication is Null if nodes.Get_Subtype_Indication(nextParameter) == nodes.Null_Iir: - param.Identifiers.append(GetNameOfNode(nextParameter)) + identifiers.append(GetNameOfNode(nextParameter)) else: parameter = nextParameter break @@ -604,7 +611,7 @@ def GetParameterFromChainedNodes( else: parameter = nodes.Get_Chain(parameter) - yield param + yield parseMethod(parseNode, identifiers) def GetMapAspect(mapAspect: Iir, cls: Type, entity: str) -> Generator[AssociationItem, None, None]: -- cgit v1.2.3 From 09b985a65469e28d46cf05a3d7e4957be84f69c7 Mon Sep 17 00:00:00 2001 From: Patrick Lehmann Date: Wed, 7 Dec 2022 00:47:11 +0100 Subject: Fixed multiple generics reading. --- pyGHDL/dom/_Translate.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pyGHDL/dom/_Translate.py b/pyGHDL/dom/_Translate.py index d39b14765..b3a48769b 100644 --- a/pyGHDL/dom/_Translate.py +++ b/pyGHDL/dom/_Translate.py @@ -471,6 +471,8 @@ def GetGenericsFromChainedNodes( if kind == nodes.Iir_Kind.Interface_Constant_Declaration: from pyGHDL.dom.InterfaceItem import GenericConstantInterfaceItem + parseNode = generic + # Lookahead for generics with multiple identifiers at once if nodes.Get_Has_Identifier_List(generic): nextNode = nodes.Get_Chain(generic) @@ -491,7 +493,7 @@ def GetGenericsFromChainedNodes( else: generic = nodes.Get_Chain(generic) - yield GenericConstantInterfaceItem.parse(generic, furtherIdentifiers) + yield GenericConstantInterfaceItem.parse(parseNode, furtherIdentifiers) furtherIdentifiers.clear() continue else: -- cgit v1.2.3 From 5853a37df7c9468a01d62f7b2eeee7d9773e72ca Mon Sep 17 00:00:00 2001 From: Patrick Lehmann Date: Mon, 19 Dec 2022 22:07:02 +0100 Subject: Restructured test example sourcefiles. --- testsuite/pyunit/SimpleEntity.vhdl | 55 --------- testsuite/pyunit/SimplePackage.vhdl | 15 --- testsuite/pyunit/dom/Simple.py | 140 +++++++++++++++++++++++ testsuite/pyunit/dom/SimpleEntity.py | 91 --------------- testsuite/pyunit/dom/examples/SimpleEntity.vhdl | 55 +++++++++ testsuite/pyunit/dom/examples/SimplePackage.vhdl | 28 +++++ 6 files changed, 223 insertions(+), 161 deletions(-) delete mode 100644 testsuite/pyunit/SimpleEntity.vhdl delete mode 100644 testsuite/pyunit/SimplePackage.vhdl create mode 100644 testsuite/pyunit/dom/Simple.py delete mode 100644 testsuite/pyunit/dom/SimpleEntity.py create mode 100644 testsuite/pyunit/dom/examples/SimpleEntity.vhdl create mode 100644 testsuite/pyunit/dom/examples/SimplePackage.vhdl diff --git a/testsuite/pyunit/SimpleEntity.vhdl b/testsuite/pyunit/SimpleEntity.vhdl deleted file mode 100644 index bdeae47e1..000000000 --- a/testsuite/pyunit/SimpleEntity.vhdl +++ /dev/null @@ -1,55 +0,0 @@ --- Author: Patrick Lehmann --- --- A generic counter module used in the StopWatch example. --- -library IEEE; -use IEEE.std_logic_1164.all; -use IEEE.numeric_std.all; - -use work.Utilities.all; - --- Generic modulo N counter --- --- This component implements a generic modulo N counter with synchronous reset --- and enable. It generates a wrap-around strobe signal when it roles from --- MODULO-1 back to zero. --- --- .. hint:: --- --- A modulo N counter counts binary from zero to N-1. --- --- This component uses VHDL-2008 features like readback of ``out`` ports. -entity Counter is - generic ( - MODULO : positive; -- Modulo value. - BITS : natural := log2(MODULO) -- Number of expected output bits. - ); - port ( - Clock : in std_logic; -- Component clock - Reset : in std_logic; -- Component reset (synchronous) - Enable : in std_logic; -- Component enable (synchronous) - - Value : out unsigned(BITS - 1 downto 0); -- Current counter value - WrapAround : out std_logic -- Strobe output on change from MODULO-1 to zero - ); -end entity; - - --- Synthesizable and simulatable variant of a generic counter. -architecture rtl of Counter is - signal CounterValue : unsigned(log2(MODULO) - 1 downto 0) := (others => '0'); -begin - process (Clock) - begin - if rising_edge(Clock) then - if ((Reset or WrapAround) = '1') then - CounterValue <= (others => '0'); - elsif (Enable = '1') then - CounterValue <= CounterValue + 1; - end if; - end if; - end process; - - Value <= resize(CounterValue, BITS); - WrapAround <= Enable when (CounterValue = MODULO - 1) else '0'; -end architecture; diff --git a/testsuite/pyunit/SimplePackage.vhdl b/testsuite/pyunit/SimplePackage.vhdl deleted file mode 100644 index dca7e15dc..000000000 --- a/testsuite/pyunit/SimplePackage.vhdl +++ /dev/null @@ -1,15 +0,0 @@ -library ieee; -use ieee.std_logic_1164.all; -use ieee.numeric_std.all; - --- Documentation before pack_1 -package pack_1 is - -- Global constant const_1 - constant const_1 : boolean := false; - -end package; - -package body pack_1 is - constant const_2 : boolean := true; - -end package body; diff --git a/testsuite/pyunit/dom/Simple.py b/testsuite/pyunit/dom/Simple.py new file mode 100644 index 000000000..32033609d --- /dev/null +++ b/testsuite/pyunit/dom/Simple.py @@ -0,0 +1,140 @@ +# ============================================================================= +# ____ _ _ ____ _ _ +# _ __ _ _ / ___| | | | _ \| | __| | ___ _ __ ___ +# | '_ \| | | | | _| |_| | | | | | / _` |/ _ \| '_ ` _ \ +# | |_) | |_| | |_| | _ | |_| | |___ | (_| | (_) | | | | | | +# | .__/ \__, |\____|_| |_|____/|_____(_)__,_|\___/|_| |_| |_| +# |_| |___/ +# ============================================================================= +# Authors: +# Patrick Lehmann +# +# Testsuite: Check libghdl IIR translation with a simple entity. +# +# 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 . +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ============================================================================ +from pathlib import Path +from unittest import TestCase + +from pyGHDL.dom.NonStandard import Design, Document + + +if __name__ == "__main__": + print("ERROR: you called a testcase declaration file as an executable module.") + print("Use: 'python -m unitest '") + exit(1) + + +class SimpleEntity(TestCase): + _root = Path(__file__).resolve().parent.parent + _filename: Path = _root / "dom/examples/SimpleEntity.vhdl" + + def test_Design(self): + design = Design() + + self.assertIsNotNone(design) + + # def test_Library(self): + # library = Library() + + def test_Document(self): + design = Design() + document = Document(self._filename) + design.Documents.append(document) + + self.assertEqual(1, len(design.Documents)) + print() + print(document.Documentation) + self.assertEqual(4, len(document.Documentation.splitlines())) + + def test_Entity(self): + design = Design() + document = Document(self._filename) + design.Documents.append(document) + + self.assertEqual(1, len(design.Documents[0].Entities)) + + entity = design.Documents[0].Entities[0] + self.assertEqual("Counter", entity.Identifier) + print() + print(entity.Documentation) + self.assertEqual(11, len(entity.Documentation.splitlines())) + + def test_Architecture(self): + design = Design() + document = Document(self._filename) + design.Documents.append(document) + + self.assertEqual(1, len(design.Documents[0].Architectures)) + + architecture = design.Documents[0].Architectures[0] + self.assertEqual("rtl", architecture.Identifier) + print() + print(architecture.Documentation) + self.assertEqual(1, len(architecture.Documentation.splitlines())) + + +class SimplePackage(TestCase): + _root = Path(__file__).resolve().parent.parent + _filename: Path = _root / "dom/examples/SimplePackage.vhdl" + + def test_Design(self): + design = Design() + + self.assertIsNotNone(design) + + # def test_Library(self): + # library = Library() + + def test_Document(self): + design = Design() + document = Document(self._filename) + design.Documents.append(document) + + self.assertEqual(1, len(design.Documents)) + print() + print(document.Documentation) + self.assertEqual(4, len(document.Documentation.splitlines())) + + def test_Package(self): + design = Design() + document = Document(self._filename) + design.Documents.append(document) + + self.assertEqual(1, len(design.Documents[0].Packages)) + + package = design.Documents[0].Packages[0] + self.assertEqual("utilities", package.Identifier) + print() + print(package.Documentation) + self.assertEqual(1, len(package.Documentation.splitlines())) + + def test_PackageBody(self): + design = Design() + document = Document(self._filename) + design.Documents.append(document) + + self.assertEqual(1, len(design.Documents[0].PackageBodies)) + + packageBodies = design.Documents[0].PackageBodies[0] + self.assertEqual("utilities", packageBodies.Identifier) + print() + print(packageBodies.Documentation) + self.assertEqual(0, len(packageBodies.Documentation.splitlines())) diff --git a/testsuite/pyunit/dom/SimpleEntity.py b/testsuite/pyunit/dom/SimpleEntity.py deleted file mode 100644 index c2167c973..000000000 --- a/testsuite/pyunit/dom/SimpleEntity.py +++ /dev/null @@ -1,91 +0,0 @@ -# ============================================================================= -# ____ _ _ ____ _ _ -# _ __ _ _ / ___| | | | _ \| | __| | ___ _ __ ___ -# | '_ \| | | | | _| |_| | | | | | / _` |/ _ \| '_ ` _ \ -# | |_) | |_| | |_| | _ | |_| | |___ | (_| | (_) | | | | | | -# | .__/ \__, |\____|_| |_|____/|_____(_)__,_|\___/|_| |_| |_| -# |_| |___/ -# ============================================================================= -# Authors: -# Patrick Lehmann -# -# Testsuite: Check libghdl IIR translation with a simple entity. -# -# 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 . -# -# SPDX-License-Identifier: GPL-2.0-or-later -# ============================================================================ -from pathlib import Path -from unittest import TestCase - -from pyGHDL.dom.NonStandard import Design, Document - - -if __name__ == "__main__": - print("ERROR: you called a testcase declaration file as an executable module.") - print("Use: 'python -m unitest '") - exit(1) - - -class SimpleEntity(TestCase): - _root = Path(__file__).resolve().parent.parent - _filename: Path = _root / "SimpleEntity.vhdl" - - def test_Design(self): - design = Design() - - self.assertIsNotNone(design) - - # def test_Library(self): - # library = Library() - - def test_Document(self): - design = Design() - document = Document(self._filename) - design.Documents.append(document) - - self.assertEqual(1, len(design.Documents)) - print() - print(document.Documentation) - self.assertEqual(4, len(document.Documentation.splitlines())) - - def test_Entity(self): - design = Design() - document = Document(self._filename) - design.Documents.append(document) - - self.assertEqual(1, len(design.Documents[0].Entities)) - - entity = design.Documents[0].Entities[0] - self.assertEqual("Counter", entity.Identifier) - print() - print(entity.Documentation) - self.assertEqual(11, len(entity.Documentation.splitlines())) - - def test_Architecture(self): - design = Design() - document = Document(self._filename) - design.Documents.append(document) - - self.assertEqual(1, len(design.Documents[0].Architectures)) - - architecture = design.Documents[0].Architectures[0] - self.assertEqual("rtl", architecture.Identifier) - print() - print(architecture.Documentation) - self.assertEqual(1, len(architecture.Documentation.splitlines())) diff --git a/testsuite/pyunit/dom/examples/SimpleEntity.vhdl b/testsuite/pyunit/dom/examples/SimpleEntity.vhdl new file mode 100644 index 000000000..bdeae47e1 --- /dev/null +++ b/testsuite/pyunit/dom/examples/SimpleEntity.vhdl @@ -0,0 +1,55 @@ +-- Author: Patrick Lehmann +-- +-- A generic counter module used in the StopWatch example. +-- +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; + +use work.Utilities.all; + +-- Generic modulo N counter +-- +-- This component implements a generic modulo N counter with synchronous reset +-- and enable. It generates a wrap-around strobe signal when it roles from +-- MODULO-1 back to zero. +-- +-- .. hint:: +-- +-- A modulo N counter counts binary from zero to N-1. +-- +-- This component uses VHDL-2008 features like readback of ``out`` ports. +entity Counter is + generic ( + MODULO : positive; -- Modulo value. + BITS : natural := log2(MODULO) -- Number of expected output bits. + ); + port ( + Clock : in std_logic; -- Component clock + Reset : in std_logic; -- Component reset (synchronous) + Enable : in std_logic; -- Component enable (synchronous) + + Value : out unsigned(BITS - 1 downto 0); -- Current counter value + WrapAround : out std_logic -- Strobe output on change from MODULO-1 to zero + ); +end entity; + + +-- Synthesizable and simulatable variant of a generic counter. +architecture rtl of Counter is + signal CounterValue : unsigned(log2(MODULO) - 1 downto 0) := (others => '0'); +begin + process (Clock) + begin + if rising_edge(Clock) then + if ((Reset or WrapAround) = '1') then + CounterValue <= (others => '0'); + elsif (Enable = '1') then + CounterValue <= CounterValue + 1; + end if; + end if; + end process; + + Value <= resize(CounterValue, BITS); + WrapAround <= Enable when (CounterValue = MODULO - 1) else '0'; +end architecture; diff --git a/testsuite/pyunit/dom/examples/SimplePackage.vhdl b/testsuite/pyunit/dom/examples/SimplePackage.vhdl new file mode 100644 index 000000000..04df1c521 --- /dev/null +++ b/testsuite/pyunit/dom/examples/SimplePackage.vhdl @@ -0,0 +1,28 @@ +-- Author: Patrick Lehmann +-- +-- A collection of utility types and functions. +-- +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +-- Utility package +package utilities is + -- Deferred constant to distinguish simulation from synthesis. + constant IS_SIMULATION : boolean; + +end package; + +package body utilities is + function simulation return boolean is + variable result : boolean := false; + begin + -- synthesis translate off + result := true; + -- synthesis translate on + return result; + end function; + + constant IS_SIMULATION : boolean := simulation; + +end package body; -- cgit v1.2.3 From 633373d0054f551158cdf668c464646bb9e6af27 Mon Sep 17 00:00:00 2001 From: Patrick Lehmann Date: Mon, 19 Dec 2022 22:11:44 +0100 Subject: Added StopWatch example for DOM and documentation testing. --- testsuite/pyunit/dom/SimplePackage.py | 63 ---------- testsuite/pyunit/dom/StopWatch.py | 95 +++++++++++++++ .../pyunit/dom/examples/StopWatch/Counter.vhdl | 45 ++++++++ .../pyunit/dom/examples/StopWatch/Debouncer.vhdl | 58 ++++++++++ .../dom/examples/StopWatch/StopWatch.pkg.vhdl | 21 ++++ .../pyunit/dom/examples/StopWatch/StopWatch.vhdl | 127 +++++++++++++++++++++ .../dom/examples/StopWatch/Utilities.pkg.vhdl | 99 ++++++++++++++++ .../dom/examples/StopWatch/seg7_Display.vhdl | 90 +++++++++++++++ .../dom/examples/StopWatch/seg7_Encoder.vhdl | 46 ++++++++ .../dom/examples/StopWatch/toplevel.Display.vhdl | 65 +++++++++++ .../dom/examples/StopWatch/toplevel.Encoder.vhdl | 42 +++++++ .../examples/StopWatch/toplevel.StopWatch.tb.vhdl | 58 ++++++++++ .../dom/examples/StopWatch/toplevel.StopWatch.vhdl | 118 +++++++++++++++++++ 13 files changed, 864 insertions(+), 63 deletions(-) delete mode 100644 testsuite/pyunit/dom/SimplePackage.py create mode 100644 testsuite/pyunit/dom/StopWatch.py create mode 100644 testsuite/pyunit/dom/examples/StopWatch/Counter.vhdl create mode 100644 testsuite/pyunit/dom/examples/StopWatch/Debouncer.vhdl create mode 100644 testsuite/pyunit/dom/examples/StopWatch/StopWatch.pkg.vhdl create mode 100644 testsuite/pyunit/dom/examples/StopWatch/StopWatch.vhdl create mode 100644 testsuite/pyunit/dom/examples/StopWatch/Utilities.pkg.vhdl create mode 100644 testsuite/pyunit/dom/examples/StopWatch/seg7_Display.vhdl create mode 100644 testsuite/pyunit/dom/examples/StopWatch/seg7_Encoder.vhdl create mode 100644 testsuite/pyunit/dom/examples/StopWatch/toplevel.Display.vhdl create mode 100644 testsuite/pyunit/dom/examples/StopWatch/toplevel.Encoder.vhdl create mode 100644 testsuite/pyunit/dom/examples/StopWatch/toplevel.StopWatch.tb.vhdl create mode 100644 testsuite/pyunit/dom/examples/StopWatch/toplevel.StopWatch.vhdl diff --git a/testsuite/pyunit/dom/SimplePackage.py b/testsuite/pyunit/dom/SimplePackage.py deleted file mode 100644 index 9c62db4a1..000000000 --- a/testsuite/pyunit/dom/SimplePackage.py +++ /dev/null @@ -1,63 +0,0 @@ -# ============================================================================= -# ____ _ _ ____ _ _ -# _ __ _ _ / ___| | | | _ \| | __| | ___ _ __ ___ -# | '_ \| | | | | _| |_| | | | | | / _` |/ _ \| '_ ` _ \ -# | |_) | |_| | |_| | _ | |_| | |___ | (_| | (_) | | | | | | -# | .__/ \__, |\____|_| |_|____/|_____(_)__,_|\___/|_| |_| |_| -# |_| |___/ -# ============================================================================= -# Authors: -# Patrick Lehmann -# -# Testsuite: Check libghdl IIR translation with a simple package. -# -# 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 . -# -# SPDX-License-Identifier: GPL-2.0-or-later -# ============================================================================ -from pathlib import Path -from unittest import TestCase - -from pyGHDL.dom.NonStandard import Design, Document - - -if __name__ == "__main__": - print("ERROR: you called a testcase declaration file as an executable module.") - print("Use: 'python -m unitest '") - exit(1) - - -class SimplePackage(TestCase): - _root = Path(__file__).resolve().parent.parent - _filename: Path = _root / "SimplePackage.vhdl" - - def test_Package(self): - design = Design() - document = Document(self._filename) - design.Documents.append(document) - - self.assertEqual(1, len(design.Documents[0].Packages)) - self.assertEqual("pack_1", design.Documents[0].Packages[0].Identifier) - - def test_PackageBody(self): - design = Design() - document = Document(self._filename) - design.Documents.append(document) - - self.assertEqual(1, len(design.Documents[0].PackageBodies)) - self.assertEqual("pack_1", design.Documents[0].PackageBodies[0].Identifier) diff --git a/testsuite/pyunit/dom/StopWatch.py b/testsuite/pyunit/dom/StopWatch.py new file mode 100644 index 000000000..a51c44cf2 --- /dev/null +++ b/testsuite/pyunit/dom/StopWatch.py @@ -0,0 +1,95 @@ +# ============================================================================= +# ____ _ _ ____ _ _ +# _ __ _ _ / ___| | | | _ \| | __| | ___ _ __ ___ +# | '_ \| | | | | _| |_| | | | | | / _` |/ _ \| '_ ` _ \ +# | |_) | |_| | |_| | _ | |_| | |___ | (_| | (_) | | | | | | +# | .__/ \__, |\____|_| |_|____/|_____(_)__,_|\___/|_| |_| |_| +# |_| |___/ +# ============================================================================= +# Authors: +# Patrick Lehmann +# +# Testsuite: Check libghdl IIR translation with a simple package. +# +# 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 . +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ============================================================================ +from pathlib import Path +from unittest import TestCase + +from pyGHDL.dom.NonStandard import Design, Document + + +if __name__ == "__main__": + print("ERROR: you called a testcase declaration file as an executable module.") + print("Use: 'python -m unitest '") + exit(1) + + +class Display(TestCase): + _root = Path(__file__).resolve().parent.parent + _sourceDirectory: Path = _root / "dom/examples/StopWatch" + + def test_Encoder(self): + design = Design() + files = ( + Path("Utilities.pkg.vhdl"), + Path("StopWatch.pkg.vhdl"), + Path("seg7_Encoder.vhdl"), + Path("toplevel.Encoder.vhdl"), + ) + for file in files: + document = Document(self._sourceDirectory / file) + design.Documents.append(document) + + self.assertEqual(len(files), len(design.Documents)) + + def test_Display(self): + design = Design() + files = ( + Path("Utilities.pkg.vhdl"), + Path("StopWatch.pkg.vhdl"), + Path("Counter.vhdl"), + Path("seg7_Encoder.vhdl"), + Path("seg7_Display.vhdl"), + Path("toplevel.Display.vhdl"), + ) + for file in files: + document = Document(self._sourceDirectory / file) + design.Documents.append(document) + + self.assertEqual(len(files), len(design.Documents)) + + def test_StopWatch(self): + design = Design() + files = ( + Path("Utilities.pkg.vhdl"), + Path("StopWatch.pkg.vhdl"), + Path("Counter.vhdl"), + Path("seg7_Encoder.vhdl"), + Path("seg7_Display.vhdl"), + Path("StopWatch.vhdl"), + Path("Debouncer.vhdl"), + Path("toplevel.StopWatch.vhdl"), + ) + for file in files: + document = Document(self._sourceDirectory / file) + design.Documents.append(document) + + self.assertEqual(len(files), len(design.Documents)) diff --git a/testsuite/pyunit/dom/examples/StopWatch/Counter.vhdl b/testsuite/pyunit/dom/examples/StopWatch/Counter.vhdl new file mode 100644 index 000000000..3ef284b98 --- /dev/null +++ b/testsuite/pyunit/dom/examples/StopWatch/Counter.vhdl @@ -0,0 +1,45 @@ +-- Author: Patrick Lehmann +-- License: MIT +-- +-- A generic counter module used in the StopWatch example. +-- +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; + +use work.Utilities.all; + + +entity Counter is + generic ( + MODULO : positive; + BITS : natural := log2(MODULO) + ); + port ( + Clock : in std_logic; + Reset : in std_logic; + Enable : in std_logic; + + Value : out unsigned(BITS - 1 downto 0); + WrapAround : out std_logic + ); +end entity; + + +architecture rtl of Counter is + signal CounterValue : unsigned(log2(MODULO) - 1 downto 0) := (others => '0'); +begin + process (Clock) + begin + if rising_edge(Clock) then + if ((Reset or WrapAround) = '1') then + CounterValue <= (others => '0'); + elsif (Enable = '1') then + CounterValue <= CounterValue + 1; + end if; + end if; + end process; + + Value <= resize(CounterValue, BITS); + WrapAround <= Enable when (CounterValue = MODULO - 1) else '0'; +end architecture; diff --git a/testsuite/pyunit/dom/examples/StopWatch/Debouncer.vhdl b/testsuite/pyunit/dom/examples/StopWatch/Debouncer.vhdl new file mode 100644 index 000000000..18207c7f1 --- /dev/null +++ b/testsuite/pyunit/dom/examples/StopWatch/Debouncer.vhdl @@ -0,0 +1,58 @@ +-- Author: Patrick Lehmann +-- License: MIT +-- +-- A generic counter module used in the StopWatch example. +-- +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; + +use work.Utilities.all; + + +entity Debouncer is + generic ( + CLOCK_PERIOD : time := 10 ns; + DEBOUNCE_TIME : time := 3 ms; + + BITS : positive + ); + port ( + Clock : in std_logic; + + Input : in std_logic_vector(BITS - 1 downto 0); + Output : out std_logic_vector(BITS - 1 downto 0) := (others => '0') + ); +end entity; + +architecture rtl of Debouncer is + constant DEBOUNCE_COUNTER_MAX : positive := DEBOUNCE_TIME / (CLOCK_PERIOD* ite(IS_SIMULATION, 20, 1)); + constant DEBOUNCE_COUNTER_BITS : positive := log2(DEBOUNCE_COUNTER_MAX); + +begin + assert false report "CLOCK_PERIOD: " & time'image(CLOCK_PERIOD); + assert false report "DEBOUNCE_TIME: " & time'image(DEBOUNCE_TIME); + --assert false report "DEBOUNCE_COUNTER_MAX: " & to_string(10 ns); + --assert false report "INTEGER'high: " & integer'image(integer'high); + + genBits: for i in Input'range generate + signal DebounceCounter : signed(DEBOUNCE_COUNTER_BITS downto 0) := to_signed(DEBOUNCE_COUNTER_MAX - 3, DEBOUNCE_COUNTER_BITS + 1); + begin + process (Clock) + begin + if rising_edge(Clock) then + -- restart counter, whenever Input(i) was unstable within DEBOUNCE_TIME_MS + if (Input(i) /= Output(i)) then + DebounceCounter <= DebounceCounter - 1; + else + DebounceCounter <= to_signed(DEBOUNCE_COUNTER_MAX - 3, DebounceCounter'length); + end if; + + -- latch input bit, if input was stable for DEBOUNCE_TIME_MS + if (DebounceCounter(DebounceCounter'high) = '1') then + Output(i) <= Input(i); + end if; + end if; + end process; + end generate; +end architecture; diff --git a/testsuite/pyunit/dom/examples/StopWatch/StopWatch.pkg.vhdl b/testsuite/pyunit/dom/examples/StopWatch/StopWatch.pkg.vhdl new file mode 100644 index 000000000..3bcafdd6d --- /dev/null +++ b/testsuite/pyunit/dom/examples/StopWatch/StopWatch.pkg.vhdl @@ -0,0 +1,21 @@ +-- Author: Patrick Lehmann +-- License: MIT +-- +-- A generic counter module used in the StopWatch example. +-- +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; + + +package StopWatch_pkg is + subtype T_BCD is unsigned(3 downto 0); + type T_BCD_Vector is array(natural range <>) of T_BCD; + + type T_DIGIT_CONFIGURATION is record + Modulo : positive; + Dot : std_logic; + end record; + + type T_STOPWATCH_CONFIGURATION is array(natural range <>) of T_DIGIT_CONFIGURATION; +end package; diff --git a/testsuite/pyunit/dom/examples/StopWatch/StopWatch.vhdl b/testsuite/pyunit/dom/examples/StopWatch/StopWatch.vhdl new file mode 100644 index 000000000..c7c9068ab --- /dev/null +++ b/testsuite/pyunit/dom/examples/StopWatch/StopWatch.vhdl @@ -0,0 +1,127 @@ +-- Author: Patrick Lehmann +-- License: MIT +-- +-- A generic counter module used in the StopWatch example. +-- +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; + +use work.Utilities.all; +use work.StopWatch_pkg.all; + + +entity Stopwatch is + generic ( + CLOCK_PERIOD : time := 10 ns; + + TIMEBASE : time; + CONFIG : T_STOPWATCH_CONFIGURATION + ); + port ( + Clock : in std_logic; + Reset : in std_logic; + + Start : in std_logic; + + Digits : out T_BCD_Vector(CONFIG'length - 1 downto 0); + Dots : out std_logic_vector(CONFIG'length - 1 downto 0) + ); +end entity; + + +architecture trl of Stopwatch is + type T_STATE is (ST_RESET, ST_IDLE, ST_COUNTING, ST_PAUSE); + + signal State : T_STATE := ST_IDLE; + signal NextState : T_STATE; + + signal FSM_Reset : std_logic; + signal FSM_Enable : std_logic; + + signal Tick : std_logic; + signal Overflows : std_logic_vector(CONFIG'length downto 0); + + +begin + process(Clock) + begin + if rising_edge(Clock) then + if (Reset = '1') then + State <= ST_RESET; + else + State <= NextState; + end if; + end if; + end process; + + process(State, Start) + begin + NextState <= State; + + FSM_Reset <= '0'; + FSM_Enable <= '0'; + + case State is + when ST_RESET => + FSM_Reset <= '1'; + NextState <= ST_IDLE; + + when ST_IDLE => + if (Start = '1') then + NextState <= ST_COUNTING; + end if; + + when ST_COUNTING => + FSM_Enable <= '1'; + + if (Start = '1') then + NextState <= ST_PAUSE; + end if; + + when ST_PAUSE => + if (Start = '1') then + NextState <= ST_COUNTING; + end if; + + when others => + NextState <= ST_RESET; + + end case; + end process; + + TimeBaseCnt: entity work.Counter + generic map ( + MODULO => TIMEBASE / (CLOCK_PERIOD * ite(IS_SIMULATION, 100, 1)), + BITS => 0 + ) + port map ( + Clock => Clock, + Reset => FSM_Reset, + Enable => FSM_Enable, + + Value => open, + WrapAround => Tick + ); + + Overflows(0) <= Tick; + + genDigits: for i in CONFIG'range generate + cnt: entity work.Counter + generic map ( + MODULO => CONFIG(i).Modulo, + BITS => Digits(i)'length + ) + port map ( + Clock => Clock, + Reset => FSM_Reset, + Enable => Overflows(i), + + Value => Digits(i), + WrapAround => Overflows(i + 1) + ); + + Dots(i) <= CONFIG(i).Dot; + end generate; + +end architecture; diff --git a/testsuite/pyunit/dom/examples/StopWatch/Utilities.pkg.vhdl b/testsuite/pyunit/dom/examples/StopWatch/Utilities.pkg.vhdl new file mode 100644 index 000000000..8daf39614 --- /dev/null +++ b/testsuite/pyunit/dom/examples/StopWatch/Utilities.pkg.vhdl @@ -0,0 +1,99 @@ +-- Author: Patrick Lehmann +-- License: MIT +-- +-- A generic counter module used in the StopWatch example. +-- +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; + + +package Utilities is + type freq is range integer'low to integer'high units + Hz; + kHz = 1000 Hz; + MHz = 1000 kHz; + GHz = 1000 MHz; + THz = 1000 GHz; + end units; + + -- deferred constant + constant IS_SIMULATION : boolean; + + function ite(condition : boolean; ThenValue : integer; ElseValue : integer) return integer; + + function log2(Value : positive) return positive; + + function bin2onehot(binary : std_logic_vector; bits : natural := 0) return std_logic_vector; + function bin2onehot(binary : unsigned; bits : natural := 0) return std_logic_vector; + + function to_index(value : unsigned; max : positive) return natural; + function to_index(value : natural; max : positive) return natural; +end package; + + +package body Utilities is + function simulation return boolean is + variable result : boolean := FALSE; + begin + -- synthesis translate_off + result := TRUE; + -- synthesis translate_on + return result; + end function; + + -- deferred constant initialization + constant IS_SIMULATION : boolean := simulation; + + function ite(condition : boolean; ThenValue : integer; ElseValue : integer) return integer is + begin + if condition then + return ThenValue; + else + return ElseValue; + end if; + end function; + + function log2(Value : positive) return positive is + variable twosPower : natural := 1; + variable result : natural := 0; + begin + while (twosPower < Value) loop + twosPower := twosPower * 2; + result := result + 1; + end loop; + return result; + end function; + + function bin2onehot(binary : std_logic_vector; bits : natural := 0) return std_logic_vector is + begin + return bin2onehot(unsigned(binary), bits); + end function; + + function bin2onehot(binary : unsigned; bits : natural := 0) return std_logic_vector is + variable result : std_logic_vector(2**binary'length - 1 downto 0) := (others => '0'); + begin + result(to_integer(binary)) := '1'; + + if (bits = 0) then + return result; + else + return result(bits - 1 downto 0); + end if; + end function; + + function to_index(value : unsigned; max : positive) return natural is + begin + return to_index(to_integer(value), max); + end function; + + function to_index(value : natural; max : positive) return natural is + begin + if (value <= max) then + return value; + else + return max; + end if; + -- return minimum(value, max); + end function; +end package body; diff --git a/testsuite/pyunit/dom/examples/StopWatch/seg7_Display.vhdl b/testsuite/pyunit/dom/examples/StopWatch/seg7_Display.vhdl new file mode 100644 index 000000000..c3771ba68 --- /dev/null +++ b/testsuite/pyunit/dom/examples/StopWatch/seg7_Display.vhdl @@ -0,0 +1,90 @@ +-- Author: Patrick Lehmann +-- License: MIT +-- +-- A generic counter module used in the StopWatch example. +-- +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; + +use work.Utilities.all; +use work.StopWatch_pkg.all; + + +entity seg7_Display is + generic ( + CLOCK_PERIOD : time := 10 ns; + REFRESH_RATE : time := 200 us; + DIGITS : positive + ); + port ( + Clock : in std_logic; + + DigitValues : in T_BCD_Vector(DIGITS - 1 downto 0); + DotValues : in std_logic_vector(DIGITS - 1 downto 0) := (others => '0'); + + Seg7_Segments : out std_logic_vector(7 downto 0); + Seg7_Selects : out std_logic_vector(DIGITS - 1 downto 0) + ); +end entity; + + +architecture rtl of seg7_Display is + constant TIMEBASE_COUNTER_MAX : positive := REFRESH_RATE / (CLOCK_PERIOD * ite(IS_SIMULATION, 1_000, 1)); + + signal Timebase_Counter : unsigned(log2(TIMEBASE_COUNTER_MAX) - 1 downto 0) := (others => '0'); + signal Timebase_Tick : std_logic; + + signal Digit_Select : unsigned(log2(DIGITS) - 1 downto 0) := (others => '0'); + signal Digit_Select_ov : std_logic; + + signal Digit : T_BCD; + signal Dot : std_logic; +begin + -- refresh rate + process(Clock) + begin + if rising_edge(Clock) then + if (Timebase_Tick = '1') then + Timebase_Counter <= (others => '0'); + else + Timebase_Counter <= Timebase_Counter + 1; + end if; + end if; + end process; + + Timebase_Tick <= '1' when (Timebase_Counter = TIMEBASE_COUNTER_MAX - 1) else '0'; + + + -- counter to select digits (time multiplexing) + process(Clock) + begin + if rising_edge(Clock) then + if (Timebase_Tick = '1') then + if (Digit_Select_ov = '1') then + Digit_Select <= (others => '0'); -- to_unsigned(5, Digit_Select'length); + else + Digit_Select <= Digit_Select + 1; + end if; + end if; + end if; + end process; + + Digit_Select_ov <= '1' when (Digit_Select = DIGITS - 1) else '0'; + + -- multiplexer + Digit <= DigitValues(to_index(Digit_Select, DigitValues'high)); + Dot <= DotValues(to_index(Digit_Select, DotValues'high)); + + -- 7-segment encoder + enc: entity work.seg7_Encoder + port map ( + BCDValue => Digit, + Dot => Dot, + + Seg7Code => Seg7_Segments + ); + + + Seg7_Selects <= bin2onehot(Digit_Select, DIGITS); +end architecture; diff --git a/testsuite/pyunit/dom/examples/StopWatch/seg7_Encoder.vhdl b/testsuite/pyunit/dom/examples/StopWatch/seg7_Encoder.vhdl new file mode 100644 index 000000000..e4c731ff9 --- /dev/null +++ b/testsuite/pyunit/dom/examples/StopWatch/seg7_Encoder.vhdl @@ -0,0 +1,46 @@ +-- Author: Patrick Lehmann +-- License: MIT +-- +-- A generic counter module used in the StopWatch example. +-- +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; + +use work.Utilities.all; +use work.StopWatch_pkg.all; + + +entity seg7_Encoder is + port ( + BCDValue : in T_BCD; + Dot : in std_logic := '0'; + + Seg7Code : out std_logic_vector(7 downto 0) + ); +end entity; + + +architecture rtl of seg7_Encoder is + +begin + process(BCDValue, Dot) + variable temp : std_logic_vector(6 downto 0); + begin + case BCDValue is -- segments: GFEDCBA -- Segment Pos. Index Pos. + when x"0" => temp := "0111111"; -- + when x"1" => temp := "0000110"; -- + when x"2" => temp := "1011011"; -- AAA 000 + when x"3" => temp := "1001111"; -- F B 5 1 + when x"4" => temp := "1100110"; -- F B 5 1 + when x"5" => temp := "1101101"; -- GGG 666 + when x"6" => temp := "1111101"; -- E C 4 2 + when x"7" => temp := "0000111"; -- E C 4 2 + when x"8" => temp := "1111111"; -- DDD DOT 333 7 + when x"9" => temp := "1101111"; -- + when others => temp := "XXXXXXX"; -- + end case; + + Seg7Code <= Dot & temp; + end process; +end architecture; diff --git a/testsuite/pyunit/dom/examples/StopWatch/toplevel.Display.vhdl b/testsuite/pyunit/dom/examples/StopWatch/toplevel.Display.vhdl new file mode 100644 index 000000000..67228a5ac --- /dev/null +++ b/testsuite/pyunit/dom/examples/StopWatch/toplevel.Display.vhdl @@ -0,0 +1,65 @@ +-- Author: Patrick Lehmann +-- License: MIT +-- +-- A generic counter module used in the StopWatch example. +-- +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; + +use work.Utilities.all; +use work.StopWatch_pkg.all; + + +entity toplevel is + generic ( + constant CLOCK_PERIOD : time := 10 ns + ); + port ( + NexysA7_SystemClock : in std_logic; + + NexysA7_GPIO_Switch : in std_logic_vector(15 downto 0); + + NexysA7_GPIO_Seg7_Cathode_n : out std_logic_vector(7 downto 0); + NexysA7_GPIO_Seg7_Anode_n : out std_logic_vector(7 downto 0) + ); +end entity; + + +architecture rtl of toplevel is + signal Digits : T_BCD_Vector(5 downto 0); + + signal Cathode : std_logic_vector(7 downto 0); + signal Anode : std_logic_vector(Digits'range); + +begin + -- connect switches to first 4 digits + genDigits: for i in 0 to 3 generate + Digits(i) <= unsigned(NexysA7_GPIO_Switch(i * 4 + 3 downto i * 4)); + end generate; + + -- do arithmetic calculations on next 2 digits + Digits(4) <= Digits(1) + Digits(0); + Digits(5) <= Digits(3) - Digits(2); + + + -- 7-segment display + display: entity work.seg7_Display + generic map ( + CLOCK_PERIOD => CLOCK_PERIOD, + DIGITS => Digits'length + ) + port map ( + Clock => NexysA7_SystemClock, + + DigitValues => Digits, + DotValues => 6d"16", + + Seg7_Segments => Cathode, + Seg7_Selects => Anode + ); + + -- convert low-active outputs + NexysA7_GPIO_Seg7_Cathode_n <= not Cathode; + NexysA7_GPIO_Seg7_Anode_n <= not ((NexysA7_GPIO_Seg7_Anode_n'high downto Anode'length => '0') & Anode); +end architecture; diff --git a/testsuite/pyunit/dom/examples/StopWatch/toplevel.Encoder.vhdl b/testsuite/pyunit/dom/examples/StopWatch/toplevel.Encoder.vhdl new file mode 100644 index 000000000..7775a6eb6 --- /dev/null +++ b/testsuite/pyunit/dom/examples/StopWatch/toplevel.Encoder.vhdl @@ -0,0 +1,42 @@ +-- Author: Patrick Lehmann +-- License: MIT +-- +-- A generic counter module used in the StopWatch example. +-- +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; + +use work.Utilities.all; +use work.StopWatch_pkg.all; + + +entity toplevel is + port ( + NexysA7_GPIO_Switch : in std_logic_vector(3 downto 0); + + NexysA7_GPIO_Seg7_Cathode_n : out std_logic_vector(7 downto 0); + NexysA7_GPIO_Seg7_Anode_n : out std_logic_vector(7 downto 0) + ); +end entity; + + +architecture rtl of toplevel is + signal Cathode : std_logic_vector(7 downto 0); + signal Anode : std_logic_vector(7 downto 0); + +begin + + -- 7-segment encoder + encoder: entity work.seg7_Encoder + port map ( + BCDValue => unsigned(NexysA7_GPIO_Switch), + Dot => '1', + + Seg7Code => Cathode + ); + + -- convert low-active outputs + NexysA7_GPIO_Seg7_Cathode_n <= not Cathode; + NexysA7_GPIO_Seg7_Anode_n <= not x"01"; +end architecture; diff --git a/testsuite/pyunit/dom/examples/StopWatch/toplevel.StopWatch.tb.vhdl b/testsuite/pyunit/dom/examples/StopWatch/toplevel.StopWatch.tb.vhdl new file mode 100644 index 000000000..a334475c4 --- /dev/null +++ b/testsuite/pyunit/dom/examples/StopWatch/toplevel.StopWatch.tb.vhdl @@ -0,0 +1,58 @@ +-- Author: Patrick Lehmann +-- License: MIT +-- +-- A generic counter module used in the StopWatch example. +-- +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; + +library lib_StopWatch; +use lib_StopWatch.Utilities.all; +use lib_StopWatch.StopWatch_pkg.all; + + +entity toplevel_tb is +end entity; + + +architecture tb of toplevel_tb is + constant CLOCK_PERIOD : time := 10 ns; + + signal StopSimulation : std_logic := '0'; + signal Clock : std_logic := '1'; + signal Reset : std_logic := '1'; + + signal StartButton : std_logic := '0'; + +begin + StopSimulation <= '1' after 30 ms; + + Clock <= (Clock xnor StopSimulation) after CLOCK_PERIOD / 2; + Reset <= '0' after 2 us, + '1' after 3 us, + '0' after 20 ms, + '1' after 20 ms + 2 us; + StartButton <= '1' after 10 us, + '0' after 15 us, + '1' after 10 ms, + '0' after 10 ms + 1 us, + '1' after 12 ms, + '0' after 12 ms + 2 us, + '1' after 22 ms, + '0' after 22 ms + 2 us; + + DUT: entity lib_StopWatch.toplevel + generic map ( + CLOCK_PERIOD_NS => CLOCK_PERIOD / 1 ns + ) + port map ( + Clock => Clock, + Reset_n => Reset, + + Button(0) => StartButton, + Seg7_Cathode_n => open, + Seg7_Anode_n => open + ); + +end architecture; diff --git a/testsuite/pyunit/dom/examples/StopWatch/toplevel.StopWatch.vhdl b/testsuite/pyunit/dom/examples/StopWatch/toplevel.StopWatch.vhdl new file mode 100644 index 000000000..1c8547446 --- /dev/null +++ b/testsuite/pyunit/dom/examples/StopWatch/toplevel.StopWatch.vhdl @@ -0,0 +1,118 @@ +-- Author: Patrick Lehmann +-- License: MIT +-- +-- A generic counter module used in the StopWatch example. +-- +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; + +use work.Utilities.all; +use work.StopWatch_pkg.all; + + +entity toplevel is + generic ( + constant CLOCK_PERIOD : time := 10 ns + ); + port ( + NexysA7_SystemClock : in std_logic; + NexysA7_GPIO_Button_Reset_n : in std_logic; + + NexysA7_GPIO_Button : in std_logic_vector(0 downto 0); + NexysA7_GPIO_Seg7_Cathode_n : out std_logic_vector(7 downto 0); + NexysA7_GPIO_Seg7_Anode_n : out std_logic_vector(7 downto 0) + ); +end entity; + + +architecture rtl of toplevel is + constant STOPWATCH_CONFIGURATION : T_STOPWATCH_CONFIGURATION := ( + 0 => (Modulo => 10, Dot => '0'), + 1 => (Modulo => 10, Dot => '0'), + 2 => (Modulo => 10, Dot => '0'), + 3 => (Modulo => 6, Dot => '0'), + 4 => (Modulo => 10, Dot => '0'), + 5 => (Modulo => 6, Dot => '0') + ); + + signal Board_Reset : std_logic; + + signal Deb_Reset : std_logic; + signal Deb_Start : std_logic; + signal Deb_Start_d : std_logic := '0'; + signal Deb_Start_re : std_logic; + + signal Reset : std_logic; + signal Start : std_logic; + + + signal Digits : T_BCD_Vector(STOPWATCH_CONFIGURATION'length - 1 downto 0); + + signal Cathode : std_logic_vector(7 downto 0); + signal Anode : std_logic_vector(Digits'range); + +begin + -- convert from low-active inputs + Board_Reset <= not NexysA7_GPIO_Button_Reset_n; + + -- Debounce input signals + deb: entity work.Debouncer + generic map ( + CLOCK_PERIOD => CLOCK_PERIOD, + BITS => 2 + ) + port map ( + Clock => NexysA7_SystemClock, + + Input(0) => Board_Reset, + Input(1) => NexysA7_GPIO_Button(0), + Output(0) => Deb_Reset, + Output(1) => Deb_Start + ); + + Reset <= Deb_Reset; + + -- Rising edge detection + Deb_Start_d <= Deb_Start when rising_edge(NexysA7_SystemClock); + Deb_Start_re <= not Deb_Start_d and Deb_Start; + + -- renaming + Start <= Deb_Start_re; + + -- Stopwatch + sw: entity work.Stopwatch + generic map ( + CLOCK_PERIOD => CLOCK_PERIOD, + + TIMEBASE => 10 ms, + CONFIG => STOPWATCH_CONFIGURATION + ) + port map ( + Clock => NexysA7_SystemClock, + Reset => Reset, + + Start => Start, + + Digits => Digits + ); + + -- 7-segment display + display: entity work.seg7_Display + generic map ( + CLOCK_PERIOD => CLOCK_PERIOD, + DIGITS => Digits'length + ) + port map ( + Clock => NexysA7_SystemClock, + + DigitValues => Digits, + + Seg7_Segments => Cathode, + Seg7_Selects => Anode + ); + + -- convert to low-active outputs + NexysA7_GPIO_Seg7_Cathode_n <= not Cathode; + NexysA7_GPIO_Seg7_Anode_n <= not ((NexysA7_GPIO_Seg7_Anode_n'high downto Anode'length => '0') & Anode); +end architecture; -- cgit v1.2.3 From cf27e918e3092fa522b9ad04a1a7d0a2dd767c75 Mon Sep 17 00:00:00 2001 From: Patrick Lehmann Date: Thu, 22 Dec 2022 10:59:24 +0100 Subject: Updated StopWatch testcode. --- testsuite/pyunit/dom/StopWatch.py | 74 +++++++++++++++++++++++---------------- 1 file changed, 43 insertions(+), 31 deletions(-) diff --git a/testsuite/pyunit/dom/StopWatch.py b/testsuite/pyunit/dom/StopWatch.py index a51c44cf2..b1065879c 100644 --- a/testsuite/pyunit/dom/StopWatch.py +++ b/testsuite/pyunit/dom/StopWatch.py @@ -42,54 +42,66 @@ if __name__ == "__main__": exit(1) -class Display(TestCase): +class Designs(TestCase): _root = Path(__file__).resolve().parent.parent _sourceDirectory: Path = _root / "dom/examples/StopWatch" + _packageFiles = ( + Path("Utilities.pkg.vhdl"), + Path("StopWatch.pkg.vhdl"), + ) + _encoderFiles = _packageFiles + ( + Path("seg7_Encoder.vhdl"), + Path("toplevel.Encoder.vhdl"), + ) + _displayFiles = _packageFiles + ( + Path("Counter.vhdl"), + Path("seg7_Encoder.vhdl"), + Path("seg7_Display.vhdl"), + Path("toplevel.Display.vhdl"), + ) + _stopwatchFiles = _packageFiles + ( + Path("Counter.vhdl"), + Path("seg7_Encoder.vhdl"), + Path("seg7_Display.vhdl"), + Path("StopWatch.vhdl"), + Path("Debouncer.vhdl"), + Path("toplevel.StopWatch.vhdl"), + ) + + +class Display(Designs): def test_Encoder(self): design = Design() - files = ( - Path("Utilities.pkg.vhdl"), - Path("StopWatch.pkg.vhdl"), - Path("seg7_Encoder.vhdl"), - Path("toplevel.Encoder.vhdl"), - ) - for file in files: + for file in self._encoderFiles: document = Document(self._sourceDirectory / file) design.Documents.append(document) - self.assertEqual(len(files), len(design.Documents)) + self.assertEqual(len(self._encoderFiles), len(design.Documents)) def test_Display(self): design = Design() - files = ( - Path("Utilities.pkg.vhdl"), - Path("StopWatch.pkg.vhdl"), - Path("Counter.vhdl"), - Path("seg7_Encoder.vhdl"), - Path("seg7_Display.vhdl"), - Path("toplevel.Display.vhdl"), - ) - for file in files: + for file in self._displayFiles: document = Document(self._sourceDirectory / file) design.Documents.append(document) - self.assertEqual(len(files), len(design.Documents)) + self.assertEqual(len(self._displayFiles), len(design.Documents)) def test_StopWatch(self): design = Design() - files = ( - Path("Utilities.pkg.vhdl"), - Path("StopWatch.pkg.vhdl"), - Path("Counter.vhdl"), - Path("seg7_Encoder.vhdl"), - Path("seg7_Display.vhdl"), - Path("StopWatch.vhdl"), - Path("Debouncer.vhdl"), - Path("toplevel.StopWatch.vhdl"), - ) - for file in files: + for file in self._stopwatchFiles: document = Document(self._sourceDirectory / file) design.Documents.append(document) - self.assertEqual(len(files), len(design.Documents)) + self.assertEqual(len(self._stopwatchFiles), len(design.Documents)) + + +class CompileOrder(Designs): + def test_Encoder(self): + design = Design() + library = design.GetLibrary("lib_StopWatch") + for file in self._encoderFiles: + document = Document(self._sourceDirectory / file) + design.AddDocument(document, library) + + design.Analyze() -- cgit v1.2.3 From acdf4682ad471089b4bddb960359820a97e6b66a Mon Sep 17 00:00:00 2001 From: Patrick Lehmann Date: Thu, 22 Dec 2022 10:59:52 +0100 Subject: Use correct API in pyVHDLModel. --- pyGHDL/dom/NonStandard.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/pyGHDL/dom/NonStandard.py b/pyGHDL/dom/NonStandard.py index eb6afd3c6..6e8f3edf1 100644 --- a/pyGHDL/dom/NonStandard.py +++ b/pyGHDL/dom/NonStandard.py @@ -201,43 +201,43 @@ class Document(VHDLModel_Document): if nodeKind == nodes.Iir_Kind.Entity_Declaration: entity = Entity.parse(libraryUnit, contextItems) - self.Entities.append(entity) + self._AddEntity(entity) elif nodeKind == nodes.Iir_Kind.Architecture_Body: architecture = Architecture.parse(libraryUnit, contextItems) - self.Architectures.append(architecture) + self._AddArchitecture(architecture) elif nodeKind == nodes.Iir_Kind.Package_Declaration: package = Package.parse(libraryUnit, contextItems) - self.Packages.append(package) + self._AddPackage(package) elif nodeKind == nodes.Iir_Kind.Package_Body: packageBody = PackageBody.parse(libraryUnit, contextItems) - self.PackageBodies.append(packageBody) + self._AddPackageBody(packageBody) elif nodeKind == nodes.Iir_Kind.Package_Instantiation_Declaration: package = PackageInstantiation.parse(libraryUnit) - self.Packages.append(package) + self._AddPackage(package) elif nodeKind == nodes.Iir_Kind.Context_Declaration: context = Context.parse(libraryUnit) - self.Contexts.append(context) + self._AddContext(context) elif nodeKind == nodes.Iir_Kind.Configuration_Declaration: configuration = Configuration.parse(libraryUnit, contextItems) - self.Configurations.append(configuration) + self._AddConfiguration(configuration) elif nodeKind == nodes.Iir_Kind.Vunit_Declaration: vunit = VerificationUnit.parse(libraryUnit) - self.VerificationUnits.append(vunit) + self._AddVerificationUnit(vunit) elif nodeKind == nodes.Iir_Kind.Vprop_Declaration: vprop = VerificationProperty.parse(libraryUnit) - self.VerificationProperties.append(vprop) + self._AddVerificationProperty(vprop) elif nodeKind == nodes.Iir_Kind.Vmode_Declaration: vmod = VerificationMode.parse(libraryUnit) - self.VerificationModes.append(vmod) + self._AddVerificationMode(vmod) else: raise DOMException(f"Unknown design unit kind '{nodeKind.name}'.") -- cgit v1.2.3 From 6cbd112a8685f4439394f21965404dd0d7c41567 Mon Sep 17 00:00:00 2001 From: Patrick Lehmann Date: Thu, 22 Dec 2022 19:11:06 +0100 Subject: Fixed path to SimpleEntity. --- testsuite/pyunit/libghdl/Initialize.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testsuite/pyunit/libghdl/Initialize.py b/testsuite/pyunit/libghdl/Initialize.py index 11bfe9a56..299b6321e 100644 --- a/testsuite/pyunit/libghdl/Initialize.py +++ b/testsuite/pyunit/libghdl/Initialize.py @@ -14,7 +14,7 @@ if __name__ == "__main__": class Instantiate(TestCase): _root = Path(__file__).resolve().parent.parent - _filename: Path = _root / "SimpleEntity.vhdl" + _filename: Path = _root / "dom/examples/SimpleEntity.vhdl" @staticmethod def getIdentifier(node): -- cgit v1.2.3 From 5e5e2fb50ed6eba32d614c9c566e280a6f992acb Mon Sep 17 00:00:00 2001 From: Patrick Lehmann Date: Thu, 22 Dec 2022 23:14:54 +0100 Subject: Changed doc comment position. --- testsuite/pyunit/dom/examples/SimpleEntity.vhdl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/testsuite/pyunit/dom/examples/SimpleEntity.vhdl b/testsuite/pyunit/dom/examples/SimpleEntity.vhdl index bdeae47e1..8acc3ddb5 100644 --- a/testsuite/pyunit/dom/examples/SimpleEntity.vhdl +++ b/testsuite/pyunit/dom/examples/SimpleEntity.vhdl @@ -35,8 +35,10 @@ entity Counter is end entity; --- Synthesizable and simulatable variant of a generic counter. architecture rtl of Counter is + -- Synthesizable and simulatable variant of a generic counter. + + -- Internal counter value signal CounterValue : unsigned(log2(MODULO) - 1 downto 0) := (others => '0'); begin process (Clock) -- cgit v1.2.3 From fbb81d6e6c30d6281e9f3b8a74c3cda41928f81c Mon Sep 17 00:00:00 2001 From: Patrick Lehmann Date: Fri, 23 Dec 2022 23:01:12 +0100 Subject: Updated to pyVHDLModel v0.18.0. --- pyGHDL/dom/DesignUnit.py | 53 ++++++++++++++++++++----------------- pyGHDL/dom/NonStandard.py | 4 +-- pyGHDL/dom/Symbol.py | 24 +++++++++++++++-- testsuite/pyunit/dom/Expressions.py | 10 ++++++- testsuite/pyunit/dom/Literals.py | 10 ++++++- testsuite/pyunit/dom/Sanity.py | 7 ++--- testsuite/pyunit/dom/Simple.py | 16 ++++++++--- 7 files changed, 86 insertions(+), 38 deletions(-) diff --git a/pyGHDL/dom/DesignUnit.py b/pyGHDL/dom/DesignUnit.py index 47eb8e766..f01c984a8 100644 --- a/pyGHDL/dom/DesignUnit.py +++ b/pyGHDL/dom/DesignUnit.py @@ -43,11 +43,15 @@ from typing import Iterable from pyTooling.Decorators import export -from pyVHDLModel import ContextUnion, EntityOrSymbol -from pyVHDLModel.SyntaxModel import ( +from pyVHDLModel import ( + ContextUnion as VHDLModel_ContextUnion, + EntityOrSymbol as VHDLModel_EntityOrSymbol, LibraryClause as VHDLModel_LibraryClause, UseClause as VHDLModel_UseClause, ContextReference as VHDLModel_ContextReference, + Name +) +from pyVHDLModel.SyntaxModel import ( Entity as VHDLModel_Entity, Architecture as VHDLModel_Architecture, Package as VHDLModel_Package, @@ -58,8 +62,7 @@ from pyVHDLModel.SyntaxModel import ( Component as VHDLModel_Component, GenericInterfaceItem, PortInterfaceItem, - Name, - ConcurrentStatement, + ConcurrentStatement, PackageReferenceSymbol, ContextReferenceSymbol, ) from pyGHDL.libghdl import utils @@ -82,41 +85,41 @@ __all__ = [] @export class LibraryClause(VHDLModel_LibraryClause, DOMMixin): - def __init__(self, libraryNode: Iir, names: Iterable[Name]): - super().__init__(names) + def __init__(self, libraryNode: Iir, symbols: Iterable[Name]): + super().__init__(symbols) DOMMixin.__init__(self, libraryNode) @export class UseClause(VHDLModel_UseClause, DOMMixin): - def __init__(self, useNode: Iir, names: Iterable[Name]): - super().__init__(names) + def __init__(self, useNode: Iir, symbols: Iterable[Name]): + super().__init__(symbols) DOMMixin.__init__(self, useNode) @classmethod def parse(cls, useNode: Iir): from pyGHDL.dom._Translate import GetNameFromNode - uses = [GetNameFromNode(nodes.Get_Selected_Name(useNode))] + uses = [PackageReferenceSymbol(GetNameFromNode(nodes.Get_Selected_Name(useNode)))] for use in utils.chain_iter(nodes.Get_Use_Clause_Chain(useNode)): - uses.append(GetNameFromNode(nodes.Get_Selected_Name(use))) + uses.append(PackageReferenceSymbol(GetNameFromNode(nodes.Get_Selected_Name(use)))) return cls(useNode, uses) @export class ContextReference(VHDLModel_ContextReference, DOMMixin): - def __init__(self, contextNode: Iir, names: Iterable[Name]): - super().__init__(names) + def __init__(self, contextNode: Iir, symbols: Iterable[Name]): + super().__init__(symbols) DOMMixin.__init__(self, contextNode) @classmethod def parse(cls, contextNode: Iir): from pyGHDL.dom._Translate import GetNameFromNode - contexts = [GetNameFromNode(nodes.Get_Selected_Name(contextNode))] + contexts = [ContextReferenceSymbol(GetNameFromNode(nodes.Get_Selected_Name(contextNode)))] for context in utils.chain_iter(nodes.Get_Context_Reference_Chain(contextNode)): - contexts.append(GetNameFromNode(nodes.Get_Selected_Name(context))) + contexts.append(ContextReferenceSymbol(GetNameFromNode(nodes.Get_Selected_Name(context)))) return cls(contextNode, contexts) @@ -127,7 +130,7 @@ class Entity(VHDLModel_Entity, DOMMixin): self, node: Iir, identifier: str, - contextItems: Iterable[ContextUnion] = None, + contextItems: Iterable[VHDLModel_ContextUnion] = None, genericItems: Iterable[GenericInterfaceItem] = None, portItems: Iterable[PortInterfaceItem] = None, declaredItems: Iterable = None, @@ -138,7 +141,7 @@ class Entity(VHDLModel_Entity, DOMMixin): DOMMixin.__init__(self, node) @classmethod - def parse(cls, entityNode: Iir, contextItems: Iterable[ContextUnion]): + def parse(cls, entityNode: Iir, contextItems: Iterable[VHDLModel_ContextUnion]): name = GetNameOfNode(entityNode) documentation = GetDocumentationOfNode(entityNode) generics = GetGenericsFromChainedNodes(nodes.Get_Generic_Chain(entityNode)) @@ -159,8 +162,8 @@ class Architecture(VHDLModel_Architecture, DOMMixin): self, node: Iir, identifier: str, - entity: EntityOrSymbol, - contextItems: Iterable[ContextUnion] = None, + entity: VHDLModel_EntityOrSymbol, + contextItems: Iterable[VHDLModel_ContextUnion] = None, declaredItems: Iterable = None, statements: Iterable["ConcurrentStatement"] = None, documentation: str = None, @@ -169,12 +172,12 @@ class Architecture(VHDLModel_Architecture, DOMMixin): DOMMixin.__init__(self, node) @classmethod - def parse(cls, architectureNode: Iir, contextItems: Iterable[ContextUnion]): + def parse(cls, architectureNode: Iir, contextItems: Iterable[VHDLModel_ContextUnion]): name = GetNameOfNode(architectureNode) documentation = GetDocumentationOfNode(architectureNode) entityNameNode = nodes.Get_Entity_Name(architectureNode) entityName = GetNameOfNode(entityNameNode) - entity = EntitySymbol(entityNameNode, SimpleName(entityNameNode, entityName)) + entitySymbol = EntitySymbol(entityNameNode, SimpleName(entityNameNode, entityName)) declaredItems = GetDeclaredItemsFromChainedNodes( nodes.Get_Declaration_Chain(architectureNode), "architecture", name ) @@ -184,7 +187,7 @@ class Architecture(VHDLModel_Architecture, DOMMixin): # FIXME: read use clauses - return cls(architectureNode, name, entity, contextItems, declaredItems, statements, documentation) + return cls(architectureNode, name, entitySymbol, contextItems, declaredItems, statements, documentation) @export @@ -216,7 +219,7 @@ class Package(VHDLModel_Package, DOMMixin): self, node: Iir, identifier: str, - contextItems: Iterable[ContextUnion] = None, + contextItems: Iterable[VHDLModel_ContextUnion] = None, genericItems: Iterable[GenericInterfaceItem] = None, declaredItems: Iterable = None, documentation: str = None, @@ -225,7 +228,7 @@ class Package(VHDLModel_Package, DOMMixin): DOMMixin.__init__(self, node) @classmethod - def parse(cls, packageNode: Iir, contextItems: Iterable[ContextUnion]): + def parse(cls, packageNode: Iir, contextItems: Iterable[VHDLModel_ContextUnion]): name = GetNameOfNode(packageNode) documentation = GetDocumentationOfNode(packageNode) @@ -248,7 +251,7 @@ class PackageBody(VHDLModel_PackageBody, DOMMixin): self, node: Iir, identifier: str, - contextItems: Iterable[ContextUnion] = None, + contextItems: Iterable[VHDLModel_ContextUnion] = None, declaredItems: Iterable = None, documentation: str = None, ): @@ -256,7 +259,7 @@ class PackageBody(VHDLModel_PackageBody, DOMMixin): DOMMixin.__init__(self, node) @classmethod - def parse(cls, packageBodyNode: Iir, contextItems: Iterable[ContextUnion]): + def parse(cls, packageBodyNode: Iir, contextItems: Iterable[VHDLModel_ContextUnion]): name = GetNameOfNode(packageBodyNode) documentation = GetDocumentationOfNode(packageBodyNode) declaredItems = GetDeclaredItemsFromChainedNodes(nodes.Get_Declaration_Chain(packageBodyNode), "package", name) diff --git a/pyGHDL/dom/NonStandard.py b/pyGHDL/dom/NonStandard.py index 6e8f3edf1..303f2c9c4 100644 --- a/pyGHDL/dom/NonStandard.py +++ b/pyGHDL/dom/NonStandard.py @@ -45,7 +45,7 @@ from pyTooling.Decorators import export from pyVHDLModel.SyntaxModel import ( Design as VHDLModel_Design, Library as VHDLModel_Library, - Document as VHDLModel_Document, + Document as VHDLModel_Document, LibraryReferenceSymbol, PackageReferenceSymbol, ContextReferenceSymbol, ) from pyGHDL.libghdl import ( @@ -183,7 +183,7 @@ class Document(VHDLModel_Document): for item in utils.chain_iter(context): itemKind = GetIirKindOfNode(item) if itemKind is nodes.Iir_Kind.Library_Clause: - contextNames.append(SimpleName(item, GetNameOfNode(item))) + contextNames.append(LibraryReferenceSymbol(SimpleName(item, GetNameOfNode(item)))) if nodes.Get_Has_Identifier_List(item): continue diff --git a/pyGHDL/dom/Symbol.py b/pyGHDL/dom/Symbol.py index c5ed39ba3..0dd0fefa9 100644 --- a/pyGHDL/dom/Symbol.py +++ b/pyGHDL/dom/Symbol.py @@ -32,10 +32,13 @@ # ============================================================================ from typing import List, Iterator -from pyTooling.Decorators import export +from pyTooling.Decorators import export, InheritDocString +from pyGHDL.dom.Names import SimpleName from pyVHDLModel.SyntaxModel import ( EntitySymbol as VHDLModel_EntitySymbol, + ArchitectureSymbol as VHDLModel_ArchitectureSymbol, + PackageSymbol as VHDLModel_PackageSymbol, SimpleSubtypeSymbol as VHDLModel_SimpleSubtypeSymbol, ConstrainedScalarSubtypeSymbol as VHDLModel_ConstrainedScalarSubtypeSymbol, ConstrainedCompositeSubtypeSymbol as VHDLModel_ConstrainedCompositeSubtypeSymbol, @@ -54,11 +57,28 @@ __all__ = [] @export class EntitySymbol(VHDLModel_EntitySymbol, DOMMixin): - def __init__(self, node: Iir, entityName: Name): + @InheritDocString(VHDLModel_EntitySymbol) + def __init__(self, node: Iir, entityName: SimpleName): super().__init__(entityName) DOMMixin.__init__(self, node) +@export +class ArchitectureSymbol(VHDLModel_ArchitectureSymbol, DOMMixin): + @InheritDocString(VHDLModel_ArchitectureSymbol) + def __init__(self, node: Iir, architectureName: SimpleName): + super().__init__(architectureName) + DOMMixin.__init__(self, node) + + +@export +class PackageSymbol(VHDLModel_PackageSymbol, DOMMixin): + @InheritDocString(VHDLModel_PackageSymbol) + def __init__(self, node: Iir, packageName: SimpleName): + super().__init__(packageName) + DOMMixin.__init__(self, node) + + @export class SimpleSubtypeSymbol(VHDLModel_SimpleSubtypeSymbol, DOMMixin): def __init__(self, node: Iir, subtypeName: Name): diff --git a/testsuite/pyunit/dom/Expressions.py b/testsuite/pyunit/dom/Expressions.py index 113e541ac..4b2e47507 100644 --- a/testsuite/pyunit/dom/Expressions.py +++ b/testsuite/pyunit/dom/Expressions.py @@ -34,6 +34,7 @@ import ctypes from inspect import currentframe from pathlib import Path from textwrap import dedent +from typing import TypeVar, Dict from unittest import TestCase @@ -51,6 +52,13 @@ if __name__ == "__main__": exit(1) +_DictKey = TypeVar("_DictKey") +_DictValue = TypeVar("_DictValue") + +def firstValue(d: Dict[_DictKey, _DictValue]) -> _DictValue: + return next(iter(d.values())) + + class Expressions(TestCase): _root = Path(__file__).resolve().parent.parent _design = Design() @@ -69,7 +77,7 @@ class Expressions(TestCase): self._design.Documents.append(document) # Traverse already to default value expression - package: Package = document.Packages[0] + package: Package = firstValue(document.Packages) item: Constant = package.DeclaredItems[0] default: Expression = item.DefaultExpression diff --git a/testsuite/pyunit/dom/Literals.py b/testsuite/pyunit/dom/Literals.py index debd401e3..9f53a6cc6 100644 --- a/testsuite/pyunit/dom/Literals.py +++ b/testsuite/pyunit/dom/Literals.py @@ -32,6 +32,7 @@ # ============================================================================ from pathlib import Path from textwrap import dedent +from typing import TypeVar, Dict from unittest import TestCase from pyVHDLModel.SyntaxModel import ExpressionUnion @@ -49,6 +50,13 @@ if __name__ == "__main__": exit(1) +_DictKey = TypeVar("_DictKey") +_DictValue = TypeVar("_DictValue") + +def firstValue(d: Dict[_DictKey, _DictValue]) -> _DictValue: + return next(iter(d.values())) + + class Literals(TestCase): _root = Path(__file__).resolve().parent.parent _design = Design() @@ -67,7 +75,7 @@ class Literals(TestCase): self._design.Documents.append(document) # Traverse already to default value expression - package: Package = document.Packages[0] + package: Package = firstValue(document.Packages) item: Constant = package.DeclaredItems[0] default: ExpressionUnion = item.DefaultExpression diff --git a/testsuite/pyunit/dom/Sanity.py b/testsuite/pyunit/dom/Sanity.py index ff5151fb3..54cb4103b 100644 --- a/testsuite/pyunit/dom/Sanity.py +++ b/testsuite/pyunit/dom/Sanity.py @@ -50,10 +50,11 @@ _SANITY_TESTS_ROOT = _TESTSUITE_ROOT / "sanity" design = Design() -@mark.parametrize("file", [str(f.relative_to(_TESTSUITE_ROOT)) for f in _SANITY_TESTS_ROOT.glob("**/*.vhdl")]) -def test_AllVHDLSources(file): +@mark.parametrize("parameters", [f"{i}:{f.relative_to(_TESTSUITE_ROOT)}" for i, f in enumerate(_SANITY_TESTS_ROOT.glob("**/*.vhdl"))]) +def test_AllVHDLSources(parameters): + id, file = parameters.split(":") filePath = _TESTSUITE_ROOT / file - lib = design.GetLibrary("sanity") + lib = design.GetLibrary(f"sanity_{id}") document = Document(filePath) design.AddDocument(document, lib) diff --git a/testsuite/pyunit/dom/Simple.py b/testsuite/pyunit/dom/Simple.py index 32033609d..82dd8579e 100644 --- a/testsuite/pyunit/dom/Simple.py +++ b/testsuite/pyunit/dom/Simple.py @@ -31,6 +31,7 @@ # SPDX-License-Identifier: GPL-2.0-or-later # ============================================================================ from pathlib import Path +from typing import TypeVar, Dict from unittest import TestCase from pyGHDL.dom.NonStandard import Design, Document @@ -42,6 +43,13 @@ if __name__ == "__main__": exit(1) +_DictKey = TypeVar("_DictKey") +_DictValue = TypeVar("_DictValue") + +def firstValue(d: Dict[_DictKey, _DictValue]) -> _DictValue: + return next(iter(d.values())) + + class SimpleEntity(TestCase): _root = Path(__file__).resolve().parent.parent _filename: Path = _root / "dom/examples/SimpleEntity.vhdl" @@ -71,7 +79,7 @@ class SimpleEntity(TestCase): self.assertEqual(1, len(design.Documents[0].Entities)) - entity = design.Documents[0].Entities[0] + entity = firstValue(design.Documents[0].Entities) self.assertEqual("Counter", entity.Identifier) print() print(entity.Documentation) @@ -84,7 +92,7 @@ class SimpleEntity(TestCase): self.assertEqual(1, len(design.Documents[0].Architectures)) - architecture = design.Documents[0].Architectures[0] + architecture = firstValue(firstValue(design.Documents[0].Architectures)) self.assertEqual("rtl", architecture.Identifier) print() print(architecture.Documentation) @@ -120,7 +128,7 @@ class SimplePackage(TestCase): self.assertEqual(1, len(design.Documents[0].Packages)) - package = design.Documents[0].Packages[0] + package = firstValue(design.Documents[0].Packages) self.assertEqual("utilities", package.Identifier) print() print(package.Documentation) @@ -133,7 +141,7 @@ class SimplePackage(TestCase): self.assertEqual(1, len(design.Documents[0].PackageBodies)) - packageBodies = design.Documents[0].PackageBodies[0] + packageBodies = firstValue(design.Documents[0].PackageBodies) self.assertEqual("utilities", packageBodies.Identifier) print() print(packageBodies.Documentation) -- cgit v1.2.3 From 91bf4124e25cf92db3394db8eec14103d6b14d7f Mon Sep 17 00:00:00 2001 From: Patrick Lehmann Date: Fri, 23 Dec 2022 23:01:44 +0100 Subject: Fixed tuple -> name. --- pyGHDL/dom/DesignUnit.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyGHDL/dom/DesignUnit.py b/pyGHDL/dom/DesignUnit.py index f01c984a8..057a2c8cd 100644 --- a/pyGHDL/dom/DesignUnit.py +++ b/pyGHDL/dom/DesignUnit.py @@ -344,7 +344,7 @@ class Configuration(VHDLModel_Configuration, DOMMixin): @classmethod def parse(cls, configurationNode: Iir, contextItems: Iterable[Context]): - name = (GetNameOfNode(configurationNode),) + name = GetNameOfNode(configurationNode) documentation = GetDocumentationOfNode(configurationNode) # FIXME: read use clauses -- cgit v1.2.3 From ef9b2610df3a24c6b9ef32d848a3512a95867834 Mon Sep 17 00:00:00 2001 From: Patrick Lehmann Date: Fri, 23 Dec 2022 23:02:07 +0100 Subject: Loading predefined libraries and packages. --- testsuite/pyunit/dom/StopWatch.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/testsuite/pyunit/dom/StopWatch.py b/testsuite/pyunit/dom/StopWatch.py index b1065879c..37b8293de 100644 --- a/testsuite/pyunit/dom/StopWatch.py +++ b/testsuite/pyunit/dom/StopWatch.py @@ -99,6 +99,8 @@ class Display(Designs): class CompileOrder(Designs): def test_Encoder(self): design = Design() + design.LoadStdLibrary() + design.LoadIEEELibrary() library = design.GetLibrary("lib_StopWatch") for file in self._encoderFiles: document = Document(self._sourceDirectory / file) -- cgit v1.2.3 From aa8d3e566996f6caa3764cb439c96e8a76fdb3be Mon Sep 17 00:00:00 2001 From: Patrick Lehmann Date: Fri, 23 Dec 2022 23:09:23 +0100 Subject: We should have asked black first. --- pyGHDL/dom/DesignUnit.py | 6 ++++-- pyGHDL/dom/NonStandard.py | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/pyGHDL/dom/DesignUnit.py b/pyGHDL/dom/DesignUnit.py index 057a2c8cd..eebf888bc 100644 --- a/pyGHDL/dom/DesignUnit.py +++ b/pyGHDL/dom/DesignUnit.py @@ -49,7 +49,7 @@ from pyVHDLModel import ( LibraryClause as VHDLModel_LibraryClause, UseClause as VHDLModel_UseClause, ContextReference as VHDLModel_ContextReference, - Name + Name, ) from pyVHDLModel.SyntaxModel import ( Entity as VHDLModel_Entity, @@ -62,7 +62,9 @@ from pyVHDLModel.SyntaxModel import ( Component as VHDLModel_Component, GenericInterfaceItem, PortInterfaceItem, - ConcurrentStatement, PackageReferenceSymbol, ContextReferenceSymbol, + ConcurrentStatement, + PackageReferenceSymbol, + ContextReferenceSymbol, ) from pyGHDL.libghdl import utils diff --git a/pyGHDL/dom/NonStandard.py b/pyGHDL/dom/NonStandard.py index 303f2c9c4..14f5e1eac 100644 --- a/pyGHDL/dom/NonStandard.py +++ b/pyGHDL/dom/NonStandard.py @@ -45,7 +45,8 @@ from pyTooling.Decorators import export from pyVHDLModel.SyntaxModel import ( Design as VHDLModel_Design, Library as VHDLModel_Library, - Document as VHDLModel_Document, LibraryReferenceSymbol, PackageReferenceSymbol, ContextReferenceSymbol, + Document as VHDLModel_Document, + LibraryReferenceSymbol, ) from pyGHDL.libghdl import ( -- cgit v1.2.3 From 5d9897770cb16494c6379cce85ed5935532c0cd1 Mon Sep 17 00:00:00 2001 From: Patrick Lehmann Date: Fri, 23 Dec 2022 23:42:01 +0100 Subject: Bumped pyVHDLModel dependency to v0.18.0. --- pyGHDL/dom/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyGHDL/dom/requirements.txt b/pyGHDL/dom/requirements.txt index 6e0c0259a..6b540d7b7 100644 --- a/pyGHDL/dom/requirements.txt +++ b/pyGHDL/dom/requirements.txt @@ -1,4 +1,4 @@ -r ../libghdl/requirements.txt -pyVHDLModel==0.17.1 +pyVHDLModel==0.18.0 #https://github.com/VHDL/pyVHDLModel/archive/dev.zip#pyVHDLModel -- cgit v1.2.3