diff options
Diffstat (limited to 'pyGHDL/dom')
-rw-r--r-- | pyGHDL/dom/Aggregates.py | 16 | ||||
-rw-r--r-- | pyGHDL/dom/Attribute.py | 4 | ||||
-rw-r--r-- | pyGHDL/dom/Concurrent.py | 791 | ||||
-rw-r--r-- | pyGHDL/dom/DesignUnit.py | 168 | ||||
-rw-r--r-- | pyGHDL/dom/Expression.py | 116 | ||||
-rw-r--r-- | pyGHDL/dom/InterfaceItem.py | 98 | ||||
-rw-r--r-- | pyGHDL/dom/Literal.py | 16 | ||||
-rw-r--r-- | pyGHDL/dom/Misc.py | 4 | ||||
-rw-r--r-- | pyGHDL/dom/Names.py | 12 | ||||
-rw-r--r-- | pyGHDL/dom/NonStandard.py | 51 | ||||
-rw-r--r-- | pyGHDL/dom/Object.py | 97 | ||||
-rw-r--r-- | pyGHDL/dom/PSL.py | 1 | ||||
-rw-r--r-- | pyGHDL/dom/Range.py | 7 | ||||
-rw-r--r-- | pyGHDL/dom/Sequential.py | 555 | ||||
-rw-r--r-- | pyGHDL/dom/Subprogram.py | 2 | ||||
-rw-r--r-- | pyGHDL/dom/Symbol.py | 6 | ||||
-rw-r--r-- | pyGHDL/dom/Type.py | 77 | ||||
-rw-r--r-- | pyGHDL/dom/_Translate.py | 604 | ||||
-rw-r--r-- | pyGHDL/dom/_Utils.py | 8 | ||||
-rw-r--r-- | pyGHDL/dom/formatting/__init__.py | 32 | ||||
-rw-r--r-- | pyGHDL/dom/formatting/prettyprint.py | 330 | ||||
-rw-r--r-- | pyGHDL/dom/requirements.txt | 2 |
22 files changed, 2595 insertions, 402 deletions
diff --git a/pyGHDL/dom/Aggregates.py b/pyGHDL/dom/Aggregates.py index 87bc44360..dfaee9a2d 100644 --- a/pyGHDL/dom/Aggregates.py +++ b/pyGHDL/dom/Aggregates.py @@ -9,7 +9,7 @@ # Authors: # Patrick Lehmann # -# Package module: DOM: VHDL design units (e.g. context or package). +# Package module: DOM: Aggregates. # # License: # ============================================================================ @@ -41,13 +41,13 @@ This module contains all DOM classes for VHDL's design units (:class:`context <E """ from pydecor import export -from pyVHDLModel.VHDLModel import ( +from pyVHDLModel.SyntaxModel import ( SimpleAggregateElement as VHDLModel_SimpleAggregateElement, IndexedAggregateElement as VHDLModel_IndexedAggregateElement, RangedAggregateElement as VHDLModel_RangedAggregateElement, NamedAggregateElement as VHDLModel_NamedAggregateElement, OthersAggregateElement as VHDLModel_OthersAggregateElement, - Expression, + ExpressionUnion, Symbol, ) from pyGHDL.libghdl._types import Iir @@ -59,34 +59,34 @@ __all__ = [] @export class SimpleAggregateElement(VHDLModel_SimpleAggregateElement, DOMMixin): - def __init__(self, node: Iir, expression: Expression): + def __init__(self, node: Iir, expression: ExpressionUnion): super().__init__(expression) DOMMixin.__init__(self, node) @export class IndexedAggregateElement(VHDLModel_IndexedAggregateElement, DOMMixin): - def __init__(self, node: Iir, index: Expression, expression: Expression): + def __init__(self, node: Iir, index: ExpressionUnion, expression: ExpressionUnion): super().__init__(index, expression) DOMMixin.__init__(self, node) @export class RangedAggregateElement(VHDLModel_RangedAggregateElement, DOMMixin): - def __init__(self, node: Iir, rng: Range, expression: Expression): + def __init__(self, node: Iir, rng: Range, expression: ExpressionUnion): super().__init__(rng, expression) DOMMixin.__init__(self, node) @export class NamedAggregateElement(VHDLModel_NamedAggregateElement, DOMMixin): - def __init__(self, node: Iir, name: Symbol, expression: Expression): + def __init__(self, node: Iir, name: Symbol, expression: ExpressionUnion): super().__init__(name, expression) DOMMixin.__init__(self, node) @export class OthersAggregateElement(VHDLModel_OthersAggregateElement, DOMMixin): - def __init__(self, node: Iir, expression: Expression): + def __init__(self, node: Iir, expression: ExpressionUnion): super().__init__(expression) DOMMixin.__init__(self, node) diff --git a/pyGHDL/dom/Attribute.py b/pyGHDL/dom/Attribute.py index 270f8feb3..97a01f65a 100644 --- a/pyGHDL/dom/Attribute.py +++ b/pyGHDL/dom/Attribute.py @@ -9,7 +9,7 @@ # Authors: # Patrick Lehmann # -# Package module: DOM: Interface items (e.g. generic or port) +# Package module: DOM: Attributes. # # License: # ============================================================================ @@ -34,7 +34,7 @@ from typing import List from pydecor import export -from pyVHDLModel.VHDLModel import ( +from pyVHDLModel.SyntaxModel import ( Attribute as VHDLModel_Attribute, AttributeSpecification as VHDLModel_AttributeSpecification, Name, diff --git a/pyGHDL/dom/Concurrent.py b/pyGHDL/dom/Concurrent.py new file mode 100644 index 000000000..e7162cc81 --- /dev/null +++ b/pyGHDL/dom/Concurrent.py @@ -0,0 +1,791 @@ +# ============================================================================= +# ____ _ _ ____ _ _ +# _ __ _ _ / ___| | | | _ \| | __| | ___ _ __ ___ +# | '_ \| | | | | _| |_| | | | | | / _` |/ _ \| '_ ` _ \ +# | |_) | |_| | |_| | _ | |_| | |___ | (_| | (_) | | | | | | +# | .__/ \__, |\____|_| |_|____/|_____(_)__,_|\___/|_| |_| |_| +# |_| |___/ +# ============================================================================= +# Authors: +# Patrick Lehmann +# +# Package module: DOM: Concurrent statements. +# +# License: +# ============================================================================ +# Copyright (C) 2019-2021 Tristan Gingold +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <gnu.org/licenses>. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ============================================================================ +from typing import Iterable + +from pydecor import export + +from pyGHDL.dom.Range import Range +from pyVHDLModel.SyntaxModel import ( + GenericAssociationItem as VHDLModel_GenericAssociationItem, + PortAssociationItem as VHDLModel_PortAssociationItem, + ParameterAssociationItem as VHDLModel_ParameterAssociationItem, + ComponentInstantiation as VHDLModel_ComponentInstantiation, + EntityInstantiation as VHDLModel_EntityInstantiation, + ConfigurationInstantiation as VHDLModel_ConfigurationInstantiation, + ConcurrentBlockStatement as VHDLModel_ConcurrentBlockStatement, + ProcessStatement as VHDLModel_ProcessStatement, + IfGenerateBranch as VHDLModel_IfGenerateBranch, + ElsifGenerateBranch as VHDLModel_ElsifGenerateBranch, + ElseGenerateBranch as VHDLModel_ElseGenerateBranch, + IfGenerateStatement as VHDLModel_IfGenerateStatement, + IndexedGenerateChoice as VHDLModel_IndexedGenerateChoice, + RangedGenerateChoice as VHDLModel_RangedGenerateChoice, + OthersGenerateCase as VHDLModel_OthersGenerateCase, + GenerateCase as VHDLModel_GenerateCase, + CaseGenerateStatement as VHDLModel_CaseGenerateStatement, + ForGenerateStatement as VHDLModel_ForGenerateStatement, + WaveformElement as VHDLModel_WaveformElement, + ConcurrentSimpleSignalAssignment as VHDLModel_ConcurrentSimpleSignalAssignment, + ConcurrentProcedureCall as VHDLModel_ConcurrentProcedureCall, + Name, + ConcurrentStatement, + SequentialStatement, + ExpressionUnion, + ConcurrentChoice, + ConcurrentCase, + AssociationItem, +) + +from pyGHDL.libghdl import Iir, utils +from pyGHDL.libghdl.vhdl import nodes +from pyGHDL.dom import DOMMixin, DOMException, Position +from pyGHDL.dom._Utils import GetNameOfNode + + +@export +class GenericAssociationItem(VHDLModel_GenericAssociationItem, DOMMixin): + def __init__( + self, associationNode: Iir, actual: ExpressionUnion, formal: Name = None + ): + super().__init__(actual, formal) + DOMMixin.__init__(self, associationNode) + + +@export +class PortAssociationItem(VHDLModel_PortAssociationItem, DOMMixin): + def __init__( + self, associationNode: Iir, actual: ExpressionUnion, formal: Name = None + ): + super().__init__(actual, formal) + DOMMixin.__init__(self, associationNode) + + +@export +class ParameterAssociationItem(VHDLModel_ParameterAssociationItem, DOMMixin): + def __init__( + self, associationNode: Iir, actual: ExpressionUnion, formal: Name = None + ): + super().__init__(actual, formal) + DOMMixin.__init__(self, associationNode) + + +@export +class ComponentInstantiation(VHDLModel_ComponentInstantiation, DOMMixin): + def __init__( + self, + instantiationNode: Iir, + label: str, + componentName: Name, + genericAssociations: Iterable[AssociationItem] = None, + portAssociations: Iterable[AssociationItem] = None, + ): + super().__init__(label, componentName, genericAssociations, portAssociations) + DOMMixin.__init__(self, instantiationNode) + + @classmethod + def parse( + cls, instantiationNode: Iir, instantiatedUnit: Iir, label: str + ) -> "ComponentInstantiation": + from pyGHDL.dom._Translate import ( + GetNameFromNode, + GetGenericMapAspect, + GetPortMapAspect, + ) + + componentName = GetNameFromNode(instantiatedUnit) + genericAssociations = GetGenericMapAspect( + nodes.Get_Generic_Map_Aspect_Chain(instantiationNode) + ) + portAssociations = GetPortMapAspect( + nodes.Get_Port_Map_Aspect_Chain(instantiationNode) + ) + + return cls( + instantiationNode, + label, + componentName, + genericAssociations, + portAssociations, + ) + + +@export +class EntityInstantiation(VHDLModel_EntityInstantiation, DOMMixin): + def __init__( + self, + instantiationNode: Iir, + label: str, + entityName: Name, + architectureName: Name = None, + genericAssociations: Iterable[AssociationItem] = None, + portAssociations: Iterable[AssociationItem] = None, + ): + super().__init__( + label, entityName, architectureName, genericAssociations, portAssociations + ) + DOMMixin.__init__(self, instantiationNode) + + @classmethod + def parse( + cls, instantiationNode: Iir, instantiatedUnit: Iir, label: str + ) -> "EntityInstantiation": + from pyGHDL.dom._Translate import ( + GetNameFromNode, + GetGenericMapAspect, + GetPortMapAspect, + ) + + entityId = nodes.Get_Entity_Name(instantiatedUnit) + entityName = GetNameFromNode(entityId) + + architectureName = None + architectureId = nodes.Get_Architecture(instantiatedUnit) + if architectureId != nodes.Null_Iir: + architectureName = GetNameOfNode(architectureId) + + genericAssociations = GetGenericMapAspect( + nodes.Get_Generic_Map_Aspect_Chain(instantiationNode) + ) + portAssociations = GetPortMapAspect( + nodes.Get_Port_Map_Aspect_Chain(instantiationNode) + ) + + return cls( + instantiationNode, + label, + entityName, + architectureName, + genericAssociations, + portAssociations, + ) + + +@export +class ConfigurationInstantiation(VHDLModel_ConfigurationInstantiation, DOMMixin): + def __init__( + self, + instantiationNode: Iir, + label: str, + configurationName: Name, + genericAssociations: Iterable[AssociationItem] = None, + portAssociations: Iterable[AssociationItem] = None, + ): + super().__init__( + label, configurationName, genericAssociations, portAssociations + ) + DOMMixin.__init__(self, instantiationNode) + + @classmethod + def parse( + cls, instantiationNode: Iir, instantiatedUnit: Iir, label: str + ) -> "ConfigurationInstantiation": + from pyGHDL.dom._Translate import ( + GetNameFromNode, + GetGenericMapAspect, + GetPortMapAspect, + ) + + configurationId = nodes.Get_Configuration_Name(instantiatedUnit) + configurationName = GetNameFromNode(configurationId) + + genericAssociations = GetGenericMapAspect( + nodes.Get_Generic_Map_Aspect_Chain(instantiationNode) + ) + portAssociations = GetPortMapAspect( + nodes.Get_Port_Map_Aspect_Chain(instantiationNode) + ) + + return cls( + instantiationNode, + label, + configurationName, + genericAssociations, + portAssociations, + ) + + +@export +class ConcurrentBlockStatement(VHDLModel_ConcurrentBlockStatement, DOMMixin): + def __init__( + self, + blockNode: Iir, + label: str, + declaredItems: Iterable = None, + statements: Iterable["ConcurrentStatement"] = None, + ): + super().__init__(label, None, declaredItems, statements) + DOMMixin.__init__(self, blockNode) + + @classmethod + def parse(cls, blockNode: Iir, label: str) -> "ConcurrentBlockStatement": + from pyGHDL.dom._Translate import ( + GetDeclaredItemsFromChainedNodes, + GetConcurrentStatementsFromChainedNodes, + ) + + # genericAssociations = GetGenericMapAspect(nodes.Get_Generic_Map_Aspect_Chain(instantiationNode)) + # portAssociations = GetPortMapAspect(nodes.Get_Port_Map_Aspect_Chain(instantiationNode)) + + declaredItems = GetDeclaredItemsFromChainedNodes( + nodes.Get_Declaration_Chain(blockNode), "block", label + ) + statements = GetConcurrentStatementsFromChainedNodes( + nodes.Get_Concurrent_Statement_Chain(blockNode), "block", label + ) + + return cls(blockNode, label, declaredItems, statements) + + +@export +class ProcessStatement(VHDLModel_ProcessStatement, DOMMixin): + def __init__( + self, + processNode: Iir, + label: str = None, + declaredItems: Iterable = None, + statements: Iterable[SequentialStatement] = None, + sensitivityList: Iterable[Name] = None, + ): + super().__init__(label, declaredItems, statements, sensitivityList) + DOMMixin.__init__(self, processNode) + + @classmethod + def parse( + cls, processNode: Iir, label: str, hasSensitivityList: bool + ) -> "ProcessStatement": + from pyGHDL.dom._Translate import ( + GetDeclaredItemsFromChainedNodes, + GetSequentialStatementsFromChainedNodes, + ) + + sensitivityList = None + if hasSensitivityList: + pass + # FIXME: sensitity list + # sensitivityListNode = nodes.Get_Sensitivity_List(processNode) + # print("sensi", GetIirKindOfNode(sensitivityListNode)) + + declaredItems = GetDeclaredItemsFromChainedNodes( + nodes.Get_Declaration_Chain(processNode), "process", label + ) + statements = GetSequentialStatementsFromChainedNodes( + nodes.Get_Sequential_Statement_Chain(processNode), "process", label + ) + + return cls(processNode, label, declaredItems, statements, sensitivityList) + + +@export +class IfGenerateBranch(VHDLModel_IfGenerateBranch): + def __init__( + self, + branchNode: Iir, + condition: ExpressionUnion, + declaredItems: Iterable = None, + statements: Iterable[ConcurrentStatement] = None, + alternativeLabel: str = None, + ): + super().__init__(condition, declaredItems, statements, alternativeLabel) + DOMMixin.__init__(self, branchNode) + + @classmethod + def parse(cls, generateNode: Iir) -> "IfGenerateBranch": + from pyGHDL.dom._Translate import ( + GetDeclaredItemsFromChainedNodes, + GetConcurrentStatementsFromChainedNodes, + GetExpressionFromNode, + ) + + condition = GetExpressionFromNode(nodes.Get_Condition(generateNode)) + body = nodes.Get_Generate_Statement_Body(generateNode) + + # TODO: alternative label + # alternativeLabelId = nodes.Get_Alternative_Label(body) + alternativeLabel = "" + + declarationChain = nodes.Get_Declaration_Chain(body) + declaredItems = GetDeclaredItemsFromChainedNodes( + declarationChain, "if-generate branch", alternativeLabel + ) + + statementChain = nodes.Get_Concurrent_Statement_Chain(body) + statements = GetConcurrentStatementsFromChainedNodes( + statementChain, "if-generate branch", alternativeLabel + ) + + return cls(generateNode, condition, declaredItems, statements, alternativeLabel) + + +@export +class ElsifGenerateBranch(VHDLModel_ElsifGenerateBranch): + def __init__( + self, + branchNode: Iir, + condition: ExpressionUnion, + declaredItems: Iterable = None, + statements: Iterable[ConcurrentStatement] = None, + alternativeLabel: str = None, + ): + super().__init__(condition, declaredItems, statements, alternativeLabel) + DOMMixin.__init__(self, branchNode) + + @classmethod + def parse(cls, generateNode: Iir, condition: Iir) -> "ElsifGenerateBranch": + from pyGHDL.dom._Translate import ( + GetDeclaredItemsFromChainedNodes, + GetConcurrentStatementsFromChainedNodes, + GetExpressionFromNode, + ) + + condition = GetExpressionFromNode(condition) + body = nodes.Get_Generate_Statement_Body(generateNode) + + # TODO: alternative label + # alternativeLabelId = nodes.Get_Alternative_Label(body) + alternativeLabel = "" + + declarationChain = nodes.Get_Declaration_Chain(body) + declaredItems = GetDeclaredItemsFromChainedNodes( + declarationChain, "elsif-generate branch", alternativeLabel + ) + + statementChain = nodes.Get_Concurrent_Statement_Chain(body) + statements = GetConcurrentStatementsFromChainedNodes( + statementChain, "elsif-generate branch", alternativeLabel + ) + + return cls(generateNode, condition, declaredItems, statements, alternativeLabel) + + +@export +class ElseGenerateBranch(VHDLModel_ElseGenerateBranch): + def __init__( + self, + branchNode: Iir, + declaredItems: Iterable = None, + statements: Iterable[ConcurrentStatement] = None, + alternativeLabel: str = None, + ): + super().__init__(declaredItems, statements, alternativeLabel) + DOMMixin.__init__(self, branchNode) + + @classmethod + def parse(cls, generateNode: Iir) -> "ElseGenerateBranch": + from pyGHDL.dom._Translate import ( + GetDeclaredItemsFromChainedNodes, + GetConcurrentStatementsFromChainedNodes, + ) + + body = nodes.Get_Generate_Statement_Body(generateNode) + + # TODO: alternative label + # alternativeLabelId = nodes.Get_Alternative_Label(body) + alternativeLabel = "" + + declarationChain = nodes.Get_Declaration_Chain(body) + declaredItems = GetDeclaredItemsFromChainedNodes( + declarationChain, "else-generate branch", alternativeLabel + ) + + statementChain = nodes.Get_Concurrent_Statement_Chain(body) + statements = GetConcurrentStatementsFromChainedNodes( + statementChain, "else-generate branch", alternativeLabel + ) + + return cls(generateNode, declaredItems, statements, alternativeLabel) + + +@export +class IfGenerateStatement(VHDLModel_IfGenerateStatement, DOMMixin): + def __init__( + self, + generateNode: Iir, + label: str, + ifBranch: IfGenerateBranch, + elsifBranches: Iterable[ElsifGenerateBranch] = None, + elseBranch: ElseGenerateBranch = None, + ): + super().__init__(label, ifBranch, elsifBranches, elseBranch) + DOMMixin.__init__(self, generateNode) + + @classmethod + def parse(cls, generateNode: Iir, label: str) -> "IfGenerateStatement": + ifBranch = IfGenerateBranch.parse(generateNode) + elsifBranches = [] + elseBranch = None + # WORKAROUND: Python 3.8 syntax + # elseClause = generateNode + # while (elseClause := nodes.Get_Generate_Else_Clause(elseClause)) != nodes.Null_Iir: + elseClause = nodes.Get_Generate_Else_Clause(generateNode) + while elseClause != nodes.Null_Iir: + condition = nodes.Get_Condition(elseClause) + if condition != nodes.Null_Iir: + elsifBranches.append(ElsifGenerateBranch.parse(elseClause, condition)) + else: + elseBranch = ElseGenerateBranch.parse(elseClause) + break + + elseClause = nodes.Get_Generate_Else_Clause(elseClause) + + return cls(generateNode, label, ifBranch, elsifBranches, elseBranch) + + +@export +class IndexedGenerateChoice(VHDLModel_IndexedGenerateChoice, DOMMixin): + def __init__(self, node: Iir, expression: ExpressionUnion): + super().__init__(expression) + DOMMixin.__init__(self, node) + + +@export +class RangedGenerateChoice(VHDLModel_RangedGenerateChoice, DOMMixin): + def __init__(self, node: Iir, rng: Range): + super().__init__(rng) + DOMMixin.__init__(self, node) + + +@export +class GenerateCase(VHDLModel_GenerateCase, DOMMixin): + def __init__( + self, + node: Iir, + choices: Iterable[ConcurrentChoice], + declaredItems: Iterable = None, + statements: Iterable[ConcurrentStatement] = None, + alternativeLabel: str = None, + ): + super().__init__(choices, declaredItems, statements, alternativeLabel) + DOMMixin.__init__(self, node) + + @classmethod + def parse( + cls, caseNode: Iir, choices: Iterable[ConcurrentChoice] + ) -> "GenerateCase": + from pyGHDL.dom._Translate import ( + GetDeclaredItemsFromChainedNodes, + GetConcurrentStatementsFromChainedNodes, + ) + + body = nodes.Get_Associated_Block(caseNode) + + # TODO: alternative label + # alternativeLabelId = nodes.Get_Alternative_Label(body) + alternativeLabel = "" + + declarationChain = nodes.Get_Declaration_Chain(body) + declaredItems = GetDeclaredItemsFromChainedNodes( + declarationChain, "generate case", alternativeLabel + ) + + statementChain = nodes.Get_Concurrent_Statement_Chain(body) + statements = GetConcurrentStatementsFromChainedNodes( + statementChain, "generate case", alternativeLabel + ) + + return cls(caseNode, choices, declaredItems, statements, alternativeLabel) + + +@export +class OthersGenerateCase(VHDLModel_OthersGenerateCase, DOMMixin): + def __init__( + self, + caseNode: Iir, + declaredItems: Iterable = None, + statements: Iterable[ConcurrentStatement] = None, + alternativeLabel: str = None, + ): + super().__init__(declaredItems, statements, alternativeLabel) + DOMMixin.__init__(self, caseNode) + + @classmethod + def parse(cls, caseNode: Iir) -> "OthersGenerateCase": + from pyGHDL.dom._Translate import ( + GetDeclaredItemsFromChainedNodes, + GetConcurrentStatementsFromChainedNodes, + ) + + body = nodes.Get_Associated_Block(caseNode) + + # TODO: alternative label + # alternativeLabelId = nodes.Get_Alternative_Label(body) + alternativeLabel = "" + + declarationChain = nodes.Get_Declaration_Chain(body) + declaredItems = GetDeclaredItemsFromChainedNodes( + declarationChain, "case-generate others", alternativeLabel + ) + + statementChain = nodes.Get_Concurrent_Statement_Chain(body) + statements = GetConcurrentStatementsFromChainedNodes( + statementChain, "case-generate others", alternativeLabel + ) + + return cls(caseNode, declaredItems, statements, alternativeLabel) + + +@export +class CaseGenerateStatement(VHDLModel_CaseGenerateStatement, DOMMixin): + def __init__( + self, + generateNode: Iir, + label: str, + expression: ExpressionUnion, + cases: Iterable[ConcurrentCase], + ): + super().__init__(label, expression, cases) + DOMMixin.__init__(self, generateNode) + + @classmethod + def parse(cls, generateNode: Iir, label: str) -> "CaseGenerateStatement": + from pyGHDL.dom._Utils import GetIirKindOfNode + from pyGHDL.dom._Translate import ( + GetExpressionFromNode, + GetRangeFromNode, + GetNameFromNode, + ) + + expression = GetExpressionFromNode(nodes.Get_Expression(generateNode)) + + cases = [] + choices = None + alternative = nodes.Get_Case_Statement_Alternative_Chain(generateNode) + caseNode = alternative + + while alternative != nodes.Null_Iir: + choiceKind = GetIirKindOfNode(alternative) + sameAlternative = nodes.Get_Same_Alternative_Flag(alternative) + + if choiceKind in ( + nodes.Iir_Kind.Choice_By_Name, + nodes.Iir_Kind.Choice_By_Expression, + ): + choiceExpression = GetExpressionFromNode( + nodes.Get_Choice_Expression(alternative) + ) + + choice = IndexedGenerateChoice(alternative, choiceExpression) + if sameAlternative: + choices.append(choice) + alternative = nodes.Get_Chain(alternative) + continue + elif choiceKind is nodes.Iir_Kind.Choice_By_Range: + choiceRange = nodes.Get_Choice_Range(alternative) + choiceRangeKind = GetIirKindOfNode(choiceRange) + if choiceRangeKind == nodes.Iir_Kind.Range_Expression: + rng = GetRangeFromNode(choiceRange) + elif choiceRangeKind in ( + nodes.Iir_Kind.Attribute_Name, + nodes.Iir_Kind.Parenthesis_Name, + ): + rng = GetNameFromNode(choiceRange) + else: + pos = Position.parse(alternative) + raise DOMException( + "Unknown choice range kind '{kind}' in case...generate statement at line {line}.".format( + kind=choiceRangeKind.name, line=pos.Line + ) + ) + + choice = RangedGenerateChoice(alternative, rng) + if sameAlternative: + choices.append(choice) + alternative = nodes.Get_Chain(alternative) + continue + elif choiceKind is nodes.Iir_Kind.Choice_By_Others: + if choices is not None: + cases.append(GenerateCase.parse(alternative, choices)) + choices = None + cases.append(OthersGenerateCase.parse(alternative)) + alternative = nodes.Get_Chain(alternative) + caseNode = alternative + continue + else: + pos = Position.parse(alternative) + raise DOMException( + "Unknown choice kind '{kind}' in case...generate statement at line {line}.".format( + kind=choiceKind.name, line=pos.Line + ) + ) + + if choices is not None: + cases.append(GenerateCase.parse(caseNode, choices)) + + caseNode = alternative + choices = [ + choice, + ] + + alternative = nodes.Get_Chain(alternative) + + if choices is not None: + cases.append(GenerateCase.parse(caseNode, choices)) + + return cls(generateNode, label, expression, cases) + + +@export +class ForGenerateStatement(VHDLModel_ForGenerateStatement, DOMMixin): + def __init__( + self, + generateNode: Iir, + label: str, + loopIndex: str, + rng: Range, + declaredItems: Iterable = None, + statements: Iterable[ConcurrentStatement] = None, + ): + super().__init__(label, loopIndex, rng, declaredItems, statements) + DOMMixin.__init__(self, generateNode) + + @classmethod + def parse(cls, generateNode: Iir, label: str) -> "ForGenerateStatement": + from pyGHDL.dom._Utils import GetIirKindOfNode + from pyGHDL.dom._Translate import ( + GetDeclaredItemsFromChainedNodes, + GetConcurrentStatementsFromChainedNodes, + GetRangeFromNode, + GetNameFromNode, + ) + + spec = nodes.Get_Parameter_Specification(generateNode) + loopIndex = GetNameOfNode(spec) + + discreteRange = nodes.Get_Discrete_Range(spec) + rangeKind = GetIirKindOfNode(discreteRange) + if rangeKind == nodes.Iir_Kind.Range_Expression: + rng = GetRangeFromNode(discreteRange) + elif rangeKind in ( + nodes.Iir_Kind.Attribute_Name, + nodes.Iir_Kind.Parenthesis_Name, + ): + rng = GetNameFromNode(discreteRange) + else: + pos = Position.parse(generateNode) + raise DOMException( + "Unknown discete range kind '{kind}' in for...generate statement at line {line}.".format( + kind=rangeKind.name, line=pos.Line + ) + ) + + body = nodes.Get_Generate_Statement_Body(generateNode) + declarationChain = nodes.Get_Declaration_Chain(body) + declaredItems = GetDeclaredItemsFromChainedNodes( + declarationChain, "for-generate", label + ) + + statementChain = nodes.Get_Concurrent_Statement_Chain(body) + statements = GetConcurrentStatementsFromChainedNodes( + statementChain, "for-generate", label + ) + + return cls(generateNode, label, loopIndex, rng, declaredItems, statements) + + +@export +class WaveformElement(VHDLModel_WaveformElement, DOMMixin): + def __init__( + self, waveNode: Iir, expression: ExpressionUnion, after: ExpressionUnion + ): + super().__init__(expression, after) + DOMMixin.__init__(self, waveNode) + + @classmethod + def parse(cls, waveNode: Iir): + from pyGHDL.dom._Translate import GetExpressionFromNode + + value = GetExpressionFromNode(nodes.Get_We_Value(waveNode)) + + timeNode = nodes.Get_Time(waveNode) + if timeNode is nodes.Null_Iir: + time = None + else: + time = GetExpressionFromNode(timeNode) + + return cls(waveNode, value, time) + + +@export +class ConcurrentSimpleSignalAssignment( + VHDLModel_ConcurrentSimpleSignalAssignment, DOMMixin +): + def __init__( + self, + assignmentNode: Iir, + label: str, + target: Name, + waveform: Iterable[WaveformElement], + ): + super().__init__(label, target, waveform) + DOMMixin.__init__(self, assignmentNode) + + @classmethod + def parse( + cls, assignmentNode: Iir, label: str + ) -> "ConcurrentSimpleSignalAssignment": + from pyGHDL.dom._Translate import GetNameFromNode + + target = nodes.Get_Target(assignmentNode) + targetName = GetNameFromNode(target) + + waveform = [] + for wave in utils.chain_iter(nodes.Get_Waveform_Chain(assignmentNode)): + waveform.append(WaveformElement.parse(wave)) + + return cls(assignmentNode, label, targetName, waveform) + + +@export +class ConcurrentProcedureCall(VHDLModel_ConcurrentProcedureCall, DOMMixin): + def __init__( + self, + callNode: Iir, + label: str, + procedureName: Name, + parameterMappings: Iterable, + ): + super().__init__(label, procedureName, parameterMappings) + DOMMixin.__init__(self, callNode) + + @classmethod + def parse(cls, concurrentCallNode: Iir, label: str) -> "ConcurrentProcedureCall": + from pyGHDL.dom._Translate import GetNameFromNode, GetParameterMapAspect + + callNode = nodes.Get_Procedure_Call(concurrentCallNode) + + prefix = nodes.Get_Prefix(callNode) + procedureName = GetNameFromNode(prefix) + parameterAssociations = GetParameterMapAspect( + nodes.Get_Parameter_Association_Chain(callNode) + ) + + return cls(concurrentCallNode, label, procedureName, parameterAssociations) diff --git a/pyGHDL/dom/DesignUnit.py b/pyGHDL/dom/DesignUnit.py index d5bf161fd..3fe8f74bf 100644 --- a/pyGHDL/dom/DesignUnit.py +++ b/pyGHDL/dom/DesignUnit.py @@ -39,12 +39,15 @@ This module contains all DOM classes for VHDL's design units (:class:`context <E """ -from typing import List +from typing import Iterable from pydecor import export -from pyVHDLModel.VHDLModel import ( +from pyVHDLModel import ContextUnion, EntityOrSymbol +from pyVHDLModel.SyntaxModel import ( + LibraryClause as VHDLModel_LibraryClause, UseClause as VHDLModel_UseClause, + ContextReference as VHDLModel_ContextReference, Entity as VHDLModel_Entity, Architecture as VHDLModel_Architecture, Package as VHDLModel_Package, @@ -55,20 +58,22 @@ from pyVHDLModel.VHDLModel import ( Component as VHDLModel_Component, GenericInterfaceItem, PortInterfaceItem, - EntityOrSymbol, Name, ConcurrentStatement, ) +from pyGHDL.libghdl import utils from pyGHDL.libghdl._types import Iir from pyGHDL.libghdl.vhdl import nodes -from pyGHDL.dom import DOMMixin +from pyGHDL.dom import DOMMixin, Position, DOMException from pyGHDL.dom._Utils import GetNameOfNode from pyGHDL.dom._Translate import ( GetGenericsFromChainedNodes, GetPortsFromChainedNodes, GetDeclaredItemsFromChainedNodes, + GetConcurrentStatementsFromChainedNodes, ) +from pyGHDL.dom.Names import SimpleName from pyGHDL.dom.Symbol import EntitySymbol @@ -76,19 +81,44 @@ __all__ = [] @export +class LibraryClause(VHDLModel_LibraryClause, DOMMixin): + def __init__(self, libraryNode: Iir, names: Iterable[Name]): + super().__init__(names) + DOMMixin.__init__(self, libraryNode) + + +@export class UseClause(VHDLModel_UseClause, DOMMixin): - def __init__(self, node: Iir, name: str): - super().__init__(name) - DOMMixin.__init__(self, node) + def __init__(self, useNode: Iir, names: Iterable[Name]): + super().__init__(names) + DOMMixin.__init__(self, useNode) @classmethod def parse(cls, useNode: Iir): from pyGHDL.dom._Translate import GetNameFromNode - selectedName = nodes.Get_Selected_Name(useNode) - name = GetNameFromNode(selectedName) + uses = [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))) - return cls(useNode, name) + return cls(useNode, uses) + + +@export +class ContextReference(VHDLModel_ContextReference, DOMMixin): + def __init__(self, contextNode: Iir, names: Iterable[Name]): + super().__init__(names) + DOMMixin.__init__(self, contextNode) + + @classmethod + def parse(cls, contextNode: Iir): + from pyGHDL.dom._Translate import GetNameFromNode + + contexts = [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))) + + return cls(contextNode, contexts) @export @@ -97,25 +127,34 @@ class Entity(VHDLModel_Entity, DOMMixin): self, node: Iir, identifier: str, - genericItems: List[GenericInterfaceItem] = None, - portItems: List[PortInterfaceItem] = None, - declaredItems: List = None, - bodyItems: List["ConcurrentStatement"] = None, + contextItems: Iterable[ContextUnion] = None, + genericItems: Iterable[GenericInterfaceItem] = None, + portItems: Iterable[PortInterfaceItem] = None, + declaredItems: Iterable = None, + statements: Iterable["ConcurrentStatement"] = None, ): - super().__init__(identifier, genericItems, portItems, declaredItems, bodyItems) + super().__init__( + identifier, contextItems, genericItems, portItems, declaredItems, statements + ) DOMMixin.__init__(self, node) @classmethod - def parse(cls, entityNode: Iir): + def parse(cls, entityNode: Iir, contextItems: Iterable[ContextUnion]): name = GetNameOfNode(entityNode) generics = GetGenericsFromChainedNodes(nodes.Get_Generic_Chain(entityNode)) ports = GetPortsFromChainedNodes(nodes.Get_Port_Chain(entityNode)) declaredItems = GetDeclaredItemsFromChainedNodes( nodes.Get_Declaration_Chain(entityNode), "entity", name ) - bodyItems = [] + statements = GetConcurrentStatementsFromChainedNodes( + nodes.Get_Concurrent_Statement_Chain(entityNode), "entity", name + ) - return cls(entityNode, name, generics, ports, declaredItems, bodyItems) + # FIXME: read use clauses + + return cls( + entityNode, name, contextItems, generics, ports, declaredItems, statements + ) @export @@ -125,27 +164,31 @@ class Architecture(VHDLModel_Architecture, DOMMixin): node: Iir, identifier: str, entity: EntityOrSymbol, - declaredItems: List = None, - bodyItems: List["ConcurrentStatement"] = None, + contextItems: Iterable[ContextUnion] = None, + declaredItems: Iterable = None, + statements: Iterable["ConcurrentStatement"] = None, ): - super().__init__(identifier, entity, declaredItems, bodyItems) + super().__init__(identifier, entity, contextItems, declaredItems, statements) DOMMixin.__init__(self, node) @classmethod - def parse(cls, architectureNode: Iir): + def parse(cls, architectureNode: Iir, contextItems: Iterable[ContextUnion]): name = GetNameOfNode(architectureNode) entityNameNode = nodes.Get_Entity_Name(architectureNode) entityName = GetNameOfNode(entityNameNode) - entity = EntitySymbol(entityNameNode, entityName) + entity = EntitySymbol(entityNameNode, SimpleName(entityNameNode, entityName)) declaredItems = GetDeclaredItemsFromChainedNodes( nodes.Get_Declaration_Chain(architectureNode), "architecture", name ) - bodyItems = [] + statements = GetConcurrentStatementsFromChainedNodes( + nodes.Get_Concurrent_Statement_Chain(architectureNode), "architecture", name + ) - return cls(architectureNode, name, entity, declaredItems, bodyItems) + # FIXME: read use clauses - def resolve(self): - pass + return cls( + architectureNode, name, entity, contextItems, declaredItems, statements + ) @export @@ -154,8 +197,8 @@ class Component(VHDLModel_Component, DOMMixin): self, node: Iir, identifier: str, - genericItems: List[GenericInterfaceItem] = None, - portItems: List[PortInterfaceItem] = None, + genericItems: Iterable[GenericInterfaceItem] = None, + portItems: Iterable[PortInterfaceItem] = None, ): super().__init__(identifier, genericItems, portItems) DOMMixin.__init__(self, node) @@ -175,14 +218,15 @@ class Package(VHDLModel_Package, DOMMixin): self, node: Iir, identifier: str, - genericItems: List[GenericInterfaceItem] = None, - declaredItems: List = None, + contextItems: Iterable[ContextUnion] = None, + genericItems: Iterable[GenericInterfaceItem] = None, + declaredItems: Iterable = None, ): - super().__init__(identifier, genericItems, declaredItems) + super().__init__(identifier, contextItems, genericItems, declaredItems) DOMMixin.__init__(self, node) @classmethod - def parse(cls, packageNode: Iir): + def parse(cls, packageNode: Iir, contextItems: Iterable[ContextUnion]): name = GetNameOfNode(packageNode) packageHeader = nodes.Get_Package_Header(packageNode) @@ -197,7 +241,9 @@ class Package(VHDLModel_Package, DOMMixin): nodes.Get_Declaration_Chain(packageNode), "package", name ) - return cls(packageNode, name, generics, declaredItems) + # FIXME: read use clauses + + return cls(packageNode, name, contextItems, generics, declaredItems) @export @@ -206,19 +252,22 @@ class PackageBody(VHDLModel_PackageBody, DOMMixin): self, node: Iir, identifier: str, - declaredItems: List = None, + contextItems: Iterable[ContextUnion] = None, + declaredItems: Iterable = None, ): - super().__init__(identifier, declaredItems) + super().__init__(identifier, contextItems, declaredItems) DOMMixin.__init__(self, node) @classmethod - def parse(cls, packageBodyNode: Iir): + def parse(cls, packageBodyNode: Iir, contextItems: Iterable[ContextUnion]): name = GetNameOfNode(packageBodyNode) declaredItems = GetDeclaredItemsFromChainedNodes( nodes.Get_Declaration_Chain(packageBodyNode), "package", name ) - return cls(packageBodyNode, name, declaredItems) + # FIXME: read use clauses + + return cls(packageBodyNode, name, contextItems, declaredItems) @export @@ -238,8 +287,10 @@ class PackageInstantiation(VHDLModel_PackageInstantiation, DOMMixin): name = GetNameOfNode(packageNode) uninstantiatedPackageName = nodes.Get_Uninstantiated_Package_Name(packageNode) + # FIXME: read use clauses (does it apply here too?) # FIXME: read generics # FIXME: read generic map + # genericAssociations = GetGenericMapAspect(nodes.Get_Generic_Map_Aspect_Chain(instantiationNode)) return cls(packageNode, name, uninstantiatedPackageName) @@ -250,17 +301,40 @@ class Context(VHDLModel_Context, DOMMixin): self, node: Iir, identifier: str, + libraryReferences: Iterable[LibraryClause] = None, + packageReferences: Iterable[UseClause] = None, ): - super().__init__(identifier) + super().__init__(identifier, libraryReferences, packageReferences) DOMMixin.__init__(self, node) @classmethod def parse(cls, contextNode: Iir): - name = GetNameOfNode(contextNode) + from pyGHDL.dom._Utils import GetIirKindOfNode - # FIXME: read use clauses + name = GetNameOfNode(contextNode) - return cls(contextNode, name) + items = [] + names = [] + for item in utils.chain_iter(nodes.Get_Context_Items(contextNode)): + kind = GetIirKindOfNode(item) + if kind is nodes.Iir_Kind.Library_Clause: + names.append(SimpleName(item, GetNameOfNode(item))) + if nodes.Get_Has_Identifier_List(item): + continue + + items.append(LibraryClause(item, names)) + names = [] + elif kind is nodes.Iir_Kind.Use_Clause: + items.append(UseClause.parse(item)) + else: + pos = Position.parse(item) + raise DOMException( + "Unknown context item kind '{kind}' in context at line {line}.".format( + kind=kind.name, line=pos.Line + ) + ) + + return cls(contextNode, name, items) @export @@ -269,14 +343,16 @@ class Configuration(VHDLModel_Configuration, DOMMixin): self, node: Iir, identifier: str, + contextItems: Iterable[Context] = None, ): - super().__init__(identifier) + super().__init__(identifier, contextItems) DOMMixin.__init__(self, node) @classmethod - def parse(cls, configurationNode: Iir): + def parse(cls, configurationNode: Iir, contextItems: Iterable[Context]): name = GetNameOfNode(configurationNode) - # FIXME: needs an implementation + # FIXME: read use clauses + # FIXME: read specifications - return cls(configurationNode, name) + return cls(configurationNode, name, contextItems) diff --git a/pyGHDL/dom/Expression.py b/pyGHDL/dom/Expression.py index 972b86ced..ce5945d46 100644 --- a/pyGHDL/dom/Expression.py +++ b/pyGHDL/dom/Expression.py @@ -9,7 +9,7 @@ # Authors: # Patrick Lehmann # -# Package module: DOM: Interface items (e.g. generic or port) +# Package module: DOM: Expressions. # # License: # ============================================================================ @@ -34,8 +34,7 @@ from typing import List, Union from pydecor import export -from pyGHDL.dom import DOMMixin, DOMException -from pyVHDLModel.VHDLModel import ( +from pyVHDLModel.SyntaxModel import ( UnaryExpression as VHDLModel_UnaryExpression, BinaryExpression as VHDLModel_BinaryExpression, InverseExpression as VHDLModel_InverseExpression, @@ -84,7 +83,7 @@ from pyVHDLModel.VHDLModel import ( SubtypeAllocation as VHDLModel_SubtypeAllocation, QualifiedExpressionAllocation as VHDLModel_QualifiedExpressionAllocation, Aggregate as VHDLModel_Aggregate, - Expression, + ExpressionUnion, AggregateElement, SubtypeOrSymbol, Symbol, @@ -93,6 +92,7 @@ from pyVHDLModel.VHDLModel import ( from pyGHDL.libghdl import utils from pyGHDL.libghdl._types import Iir from pyGHDL.libghdl.vhdl import nodes +from pyGHDL.dom import DOMMixin, DOMException, Position from pyGHDL.dom._Utils import GetIirKindOfNode from pyGHDL.dom.Symbol import SimpleSubtypeSymbol from pyGHDL.dom.Aggregates import ( @@ -130,7 +130,7 @@ class _ParseBinaryExpressionMixin: class InverseExpression( VHDLModel_InverseExpression, DOMMixin, _ParseUnaryExpressionMixin ): - def __init__(self, node: Iir, operand: Expression): + def __init__(self, node: Iir, operand: ExpressionUnion): super().__init__(operand) DOMMixin.__init__(self, node) @@ -139,7 +139,7 @@ class InverseExpression( class IdentityExpression( VHDLModel_IdentityExpression, DOMMixin, _ParseUnaryExpressionMixin ): - def __init__(self, node: Iir, operand: Expression): + def __init__(self, node: Iir, operand: ExpressionUnion): super().__init__(operand) DOMMixin.__init__(self, node) @@ -148,7 +148,7 @@ class IdentityExpression( class NegationExpression( VHDLModel_NegationExpression, DOMMixin, _ParseUnaryExpressionMixin ): - def __init__(self, node: Iir, operand: Expression): + def __init__(self, node: Iir, operand: ExpressionUnion): super().__init__(operand) DOMMixin.__init__(self, node) @@ -157,7 +157,7 @@ class NegationExpression( class AbsoluteExpression( VHDLModel_AbsoluteExpression, DOMMixin, _ParseUnaryExpressionMixin ): - def __init__(self, node: Iir, operand: Expression): + def __init__(self, node: Iir, operand: ExpressionUnion): super().__init__(operand) DOMMixin.__init__(self, node) @@ -166,7 +166,7 @@ class AbsoluteExpression( class ParenthesisExpression( VHDLModel_ParenthesisExpression, DOMMixin, _ParseUnaryExpressionMixin ): - def __init__(self, node: Iir, operand: Expression): + def __init__(self, node: Iir, operand: ExpressionUnion): super().__init__(operand) DOMMixin.__init__(self, node) @@ -180,14 +180,14 @@ class ParenthesisExpression( @export class TypeConversion(VHDLModel_TypeConversion, DOMMixin): - def __init__(self, node: Iir, operand: Expression): + def __init__(self, node: Iir, operand: ExpressionUnion): super().__init__(operand) DOMMixin.__init__(self, node) @export class FunctionCall(VHDLModel_FunctionCall, DOMMixin): - def __init__(self, node: Iir, operand: Expression): + def __init__(self, node: Iir, operand: ExpressionUnion): super().__init__() DOMMixin.__init__(self, node) @@ -211,14 +211,14 @@ class RangeExpression(VHDLModel_RangeExpression, DOMMixin): @export class AscendingRangeExpression(VHDLModel_AscendingRangeExpression, DOMMixin): - def __init__(self, node: Iir, left: Expression, right: Expression): + def __init__(self, node: Iir, left: ExpressionUnion, right: ExpressionUnion): super().__init__(left, right) DOMMixin.__init__(self, node) @export class DescendingRangeExpression(VHDLModel_DescendingRangeExpression, DOMMixin): - def __init__(self, node: Iir, left: Expression, right: Expression): + def __init__(self, node: Iir, left: ExpressionUnion, right: ExpressionUnion): super().__init__(left, right) DOMMixin.__init__(self, node) @@ -227,7 +227,7 @@ class DescendingRangeExpression(VHDLModel_DescendingRangeExpression, DOMMixin): class AdditionExpression( VHDLModel_AdditionExpression, DOMMixin, _ParseBinaryExpressionMixin ): - def __init__(self, node: Iir, left: Expression, right: Expression): + def __init__(self, node: Iir, left: ExpressionUnion, right: ExpressionUnion): super().__init__(left, right) DOMMixin.__init__(self, node) @@ -236,7 +236,7 @@ class AdditionExpression( class SubtractionExpression( VHDLModel_SubtractionExpression, DOMMixin, _ParseBinaryExpressionMixin ): - def __init__(self, node: Iir, left: Expression, right: Expression): + def __init__(self, node: Iir, left: ExpressionUnion, right: ExpressionUnion): super().__init__(left, right) DOMMixin.__init__(self, node) @@ -245,7 +245,7 @@ class SubtractionExpression( class ConcatenationExpression( VHDLModel_ConcatenationExpression, DOMMixin, _ParseBinaryExpressionMixin ): - def __init__(self, node: Iir, left: Expression, right: Expression): + def __init__(self, node: Iir, left: ExpressionUnion, right: ExpressionUnion): super().__init__(left, right) DOMMixin.__init__(self, node) @@ -254,7 +254,7 @@ class ConcatenationExpression( class MultiplyExpression( VHDLModel_MultiplyExpression, DOMMixin, _ParseBinaryExpressionMixin ): - def __init__(self, node: Iir, left: Expression, right: Expression): + def __init__(self, node: Iir, left: ExpressionUnion, right: ExpressionUnion): super().__init__(left, right) DOMMixin.__init__(self, node) @@ -263,7 +263,7 @@ class MultiplyExpression( class DivisionExpression( VHDLModel_DivisionExpression, DOMMixin, _ParseBinaryExpressionMixin ): - def __init__(self, node: Iir, left: Expression, right: Expression): + def __init__(self, node: Iir, left: ExpressionUnion, right: ExpressionUnion): super().__init__(left, right) DOMMixin.__init__(self, node) @@ -272,7 +272,7 @@ class DivisionExpression( class RemainderExpression( VHDLModel_RemainderExpression, DOMMixin, _ParseBinaryExpressionMixin ): - def __init__(self, node: Iir, left: Expression, right: Expression): + def __init__(self, node: Iir, left: ExpressionUnion, right: ExpressionUnion): super().__init__(left, right) DOMMixin.__init__(self, node) @@ -281,7 +281,7 @@ class RemainderExpression( class ModuloExpression( VHDLModel_ModuloExpression, DOMMixin, _ParseBinaryExpressionMixin ): - def __init__(self, node: Iir, left: Expression, right: Expression): + def __init__(self, node: Iir, left: ExpressionUnion, right: ExpressionUnion): super().__init__(left, right) DOMMixin.__init__(self, node) @@ -290,56 +290,56 @@ class ModuloExpression( class ExponentiationExpression( VHDLModel_ExponentiationExpression, DOMMixin, _ParseBinaryExpressionMixin ): - def __init__(self, node: Iir, left: Expression, right: Expression): + def __init__(self, node: Iir, left: ExpressionUnion, right: ExpressionUnion): super().__init__(left, right) DOMMixin.__init__(self, node) @export class AndExpression(VHDLModel_AndExpression, DOMMixin, _ParseBinaryExpressionMixin): - def __init__(self, node: Iir, left: Expression, right: Expression): + def __init__(self, node: Iir, left: ExpressionUnion, right: ExpressionUnion): super().__init__(left, right) DOMMixin.__init__(self, node) @export class NandExpression(VHDLModel_NandExpression, DOMMixin, _ParseBinaryExpressionMixin): - def __init__(self, node: Iir, left: Expression, right: Expression): + def __init__(self, node: Iir, left: ExpressionUnion, right: ExpressionUnion): super().__init__(left, right) DOMMixin.__init__(self, node) @export class OrExpression(VHDLModel_OrExpression, DOMMixin, _ParseBinaryExpressionMixin): - def __init__(self, node: Iir, left: Expression, right: Expression): + def __init__(self, node: Iir, left: ExpressionUnion, right: ExpressionUnion): super().__init__(left, right) DOMMixin.__init__(self, node) @export class NorExpression(VHDLModel_NorExpression, DOMMixin, _ParseBinaryExpressionMixin): - def __init__(self, node: Iir, left: Expression, right: Expression): + def __init__(self, node: Iir, left: ExpressionUnion, right: ExpressionUnion): super().__init__(left, right) DOMMixin.__init__(self, node) @export class XorExpression(VHDLModel_XorExpression, DOMMixin, _ParseBinaryExpressionMixin): - def __init__(self, node: Iir, left: Expression, right: Expression): + def __init__(self, node: Iir, left: ExpressionUnion, right: ExpressionUnion): super().__init__(left, right) DOMMixin.__init__(self, node) @export class XnorExpression(VHDLModel_XnorExpression, DOMMixin, _ParseBinaryExpressionMixin): - def __init__(self, node: Iir, left: Expression, right: Expression): + def __init__(self, node: Iir, left: ExpressionUnion, right: ExpressionUnion): super().__init__(left, right) DOMMixin.__init__(self, node) @export class EqualExpression(VHDLModel_EqualExpression, DOMMixin, _ParseBinaryExpressionMixin): - def __init__(self, node: Iir, left: Expression, right: Expression): + def __init__(self, node: Iir, left: ExpressionUnion, right: ExpressionUnion): super().__init__(left, right) DOMMixin.__init__(self, node) @@ -348,7 +348,7 @@ class EqualExpression(VHDLModel_EqualExpression, DOMMixin, _ParseBinaryExpressio class UnequalExpression( VHDLModel_UnequalExpression, DOMMixin, _ParseBinaryExpressionMixin ): - def __init__(self, node: Iir, left: Expression, right: Expression): + def __init__(self, node: Iir, left: ExpressionUnion, right: ExpressionUnion): super().__init__(left, right) DOMMixin.__init__(self, node) @@ -357,7 +357,7 @@ class UnequalExpression( class LessThanExpression( VHDLModel_LessThanExpression, DOMMixin, _ParseBinaryExpressionMixin ): - def __init__(self, node: Iir, left: Expression, right: Expression): + def __init__(self, node: Iir, left: ExpressionUnion, right: ExpressionUnion): super().__init__(left, right) DOMMixin.__init__(self, node) @@ -366,7 +366,7 @@ class LessThanExpression( class LessEqualExpression( VHDLModel_LessEqualExpression, DOMMixin, _ParseBinaryExpressionMixin ): - def __init__(self, node: Iir, left: Expression, right: Expression): + def __init__(self, node: Iir, left: ExpressionUnion, right: ExpressionUnion): super().__init__(left, right) DOMMixin.__init__(self, node) @@ -375,7 +375,7 @@ class LessEqualExpression( class GreaterThanExpression( VHDLModel_GreaterThanExpression, DOMMixin, _ParseBinaryExpressionMixin ): - def __init__(self, node: Iir, left: Expression, right: Expression): + def __init__(self, node: Iir, left: ExpressionUnion, right: ExpressionUnion): super().__init__(left, right) DOMMixin.__init__(self, node) @@ -384,7 +384,7 @@ class GreaterThanExpression( class GreaterEqualExpression( VHDLModel_GreaterEqualExpression, DOMMixin, _ParseBinaryExpressionMixin ): - def __init__(self, node: Iir, left: Expression, right: Expression): + def __init__(self, node: Iir, left: ExpressionUnion, right: ExpressionUnion): super().__init__(left, right) DOMMixin.__init__(self, node) @@ -393,7 +393,7 @@ class GreaterEqualExpression( class MatchingEqualExpression( VHDLModel_MatchingEqualExpression, DOMMixin, _ParseBinaryExpressionMixin ): - def __init__(self, node: Iir, left: Expression, right: Expression): + def __init__(self, node: Iir, left: ExpressionUnion, right: ExpressionUnion): super().__init__(left, right) DOMMixin.__init__(self, node) @@ -402,7 +402,7 @@ class MatchingEqualExpression( class MatchingUnequalExpression( VHDLModel_MatchingUnequalExpression, DOMMixin, _ParseBinaryExpressionMixin ): - def __init__(self, node: Iir, left: Expression, right: Expression): + def __init__(self, node: Iir, left: ExpressionUnion, right: ExpressionUnion): super().__init__(left, right) DOMMixin.__init__(self, node) @@ -411,7 +411,7 @@ class MatchingUnequalExpression( class MatchingLessThanExpression( VHDLModel_MatchingLessThanExpression, DOMMixin, _ParseBinaryExpressionMixin ): - def __init__(self, node: Iir, left: Expression, right: Expression): + def __init__(self, node: Iir, left: ExpressionUnion, right: ExpressionUnion): super().__init__(left, right) DOMMixin.__init__(self, node) @@ -420,7 +420,7 @@ class MatchingLessThanExpression( class MatchingLessEqualExpression( VHDLModel_MatchingLessEqualExpression, DOMMixin, _ParseBinaryExpressionMixin ): - def __init__(self, node: Iir, left: Expression, right: Expression): + def __init__(self, node: Iir, left: ExpressionUnion, right: ExpressionUnion): super().__init__(left, right) DOMMixin.__init__(self, node) @@ -429,7 +429,7 @@ class MatchingLessEqualExpression( class MatchingGreaterThanExpression( VHDLModel_MatchingGreaterThanExpression, DOMMixin, _ParseBinaryExpressionMixin ): - def __init__(self, node: Iir, left: Expression, right: Expression): + def __init__(self, node: Iir, left: ExpressionUnion, right: ExpressionUnion): super().__init__(left, right) DOMMixin.__init__(self, node) @@ -438,7 +438,7 @@ class MatchingGreaterThanExpression( class MatchingGreaterEqualExpression( VHDLModel_MatchingGreaterEqualExpression, DOMMixin, _ParseBinaryExpressionMixin ): - def __init__(self, node: Iir, left: Expression, right: Expression): + def __init__(self, node: Iir, left: ExpressionUnion, right: ExpressionUnion): super().__init__(left, right) DOMMixin.__init__(self, node) @@ -447,7 +447,7 @@ class MatchingGreaterEqualExpression( class ShiftRightLogicExpression( VHDLModel_ShiftRightLogicExpression, DOMMixin, _ParseBinaryExpressionMixin ): - def __init__(self, node: Iir, left: Expression, right: Expression): + def __init__(self, node: Iir, left: ExpressionUnion, right: ExpressionUnion): super().__init__(left, right) DOMMixin.__init__(self, node) @@ -456,7 +456,7 @@ class ShiftRightLogicExpression( class ShiftLeftLogicExpression( VHDLModel_ShiftLeftLogicExpression, DOMMixin, _ParseBinaryExpressionMixin ): - def __init__(self, node: Iir, left: Expression, right: Expression): + def __init__(self, node: Iir, left: ExpressionUnion, right: ExpressionUnion): super().__init__(left, right) DOMMixin.__init__(self, node) @@ -465,7 +465,7 @@ class ShiftLeftLogicExpression( class ShiftRightArithmeticExpression( VHDLModel_ShiftRightArithmeticExpression, DOMMixin, _ParseBinaryExpressionMixin ): - def __init__(self, node: Iir, left: Expression, right: Expression): + def __init__(self, node: Iir, left: ExpressionUnion, right: ExpressionUnion): super().__init__(left, right) DOMMixin.__init__(self, node) @@ -474,7 +474,7 @@ class ShiftRightArithmeticExpression( class ShiftLeftArithmeticExpression( VHDLModel_ShiftLeftArithmeticExpression, DOMMixin, _ParseBinaryExpressionMixin ): - def __init__(self, node: Iir, left: Expression, right: Expression): + def __init__(self, node: Iir, left: ExpressionUnion, right: ExpressionUnion): super().__init__(left, right) DOMMixin.__init__(self, node) @@ -483,7 +483,7 @@ class ShiftLeftArithmeticExpression( class RotateRightExpression( VHDLModel_RotateRightExpression, DOMMixin, _ParseBinaryExpressionMixin ): - def __init__(self, node: Iir, left: Expression, right: Expression): + def __init__(self, node: Iir, left: ExpressionUnion, right: ExpressionUnion): super().__init__(left, right) DOMMixin.__init__(self, node) @@ -492,14 +492,14 @@ class RotateRightExpression( class RotateLeftExpression( VHDLModel_RotateLeftExpression, DOMMixin, _ParseBinaryExpressionMixin ): - def __init__(self, node: Iir, left: Expression, right: Expression): + def __init__(self, node: Iir, left: ExpressionUnion, right: ExpressionUnion): super().__init__(left, right) DOMMixin.__init__(self, node) @export class QualifiedExpression(VHDLModel_QualifiedExpression, DOMMixin): - def __init__(self, node: Iir, subtype: SubtypeOrSymbol, operand: Expression): + def __init__(self, node: Iir, subtype: SubtypeOrSymbol, operand: ExpressionUnion): super().__init__(subtype, operand) DOMMixin.__init__(self, node) @@ -570,8 +570,24 @@ class Aggregate(VHDLModel_Aggregate, DOMMixin): index = GetExpressionFromNode(nodes.Get_Choice_Expression(item)) choices.append(IndexedAggregateElement(item, index, value)) elif kind == nodes.Iir_Kind.Choice_By_Range: - r = GetRangeFromNode(nodes.Get_Choice_Range(item)) - choices.append(RangedAggregateElement(item, r, value)) + choiceRange = nodes.Get_Choice_Range(item) + rangeKind = GetIirKindOfNode(choiceRange) + if rangeKind == nodes.Iir_Kind.Range_Expression: + rng = GetRangeFromNode(choiceRange) + elif rangeKind in ( + nodes.Iir_Kind.Attribute_Name, + nodes.Iir_Kind.Parenthesis_Name, + ): + rng = GetNameFromNode(choiceRange) + else: + pos = Position.parse(item) + raise DOMException( + "Unknown discete range kind '{kind}' in for...generate statement at line {line}.".format( + kind=rangeKind.name, line=pos.Line + ) + ) + + choices.append(RangedAggregateElement(item, rng, value)) elif kind == nodes.Iir_Kind.Choice_By_Name: name = GetNameFromNode(nodes.Get_Choice_Name(item)) symbol = Symbol(item, name) @@ -580,8 +596,8 @@ class Aggregate(VHDLModel_Aggregate, DOMMixin): choices.append(OthersAggregateElement(item, value)) else: raise DOMException( - "Unknown choice kind '{kindName}'({kind}) in aggregate '{aggr}'.".format( - kind=kind, kindName=kind.name, aggr=node + "Unknown choice kind '{kind}' in aggregate '{aggr}'.".format( + kind=kind.name, aggr=node ) ) diff --git a/pyGHDL/dom/InterfaceItem.py b/pyGHDL/dom/InterfaceItem.py index 4ebea735a..af1b681cd 100644 --- a/pyGHDL/dom/InterfaceItem.py +++ b/pyGHDL/dom/InterfaceItem.py @@ -30,9 +30,11 @@ # # SPDX-License-Identifier: GPL-2.0-or-later # ============================================================================ +from typing import List + from pydecor import export -from pyVHDLModel.VHDLModel import ( +from pyVHDLModel.SyntaxModel import ( GenericConstantInterfaceItem as VHDLModel_GenericConstantInterfaceItem, GenericTypeInterfaceItem as VHDLModel_GenericTypeInterfaceItem, GenericPackageInterfaceItem as VHDLModel_GenericPackageInterfaceItem, @@ -45,7 +47,7 @@ from pyVHDLModel.VHDLModel import ( ParameterFileInterfaceItem as VHDLModel_ParameterFileInterfaceItem, Mode, SubtypeOrSymbol, - Expression, + ExpressionUnion, ) from pyGHDL.libghdl._types import Iir @@ -63,12 +65,12 @@ class GenericConstantInterfaceItem(VHDLModel_GenericConstantInterfaceItem, DOMMi def __init__( self, node: Iir, - identifier: str, + identifiers: List[str], mode: Mode, subtype: SubtypeOrSymbol, - defaultExpression: Expression, + defaultExpression: ExpressionUnion, ): - super().__init__(identifier, mode, subtype, defaultExpression) + super().__init__(identifiers, mode, subtype, defaultExpression) DOMMixin.__init__(self, node) @classmethod @@ -79,7 +81,15 @@ class GenericConstantInterfaceItem(VHDLModel_GenericConstantInterfaceItem, DOMMi 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, + ) @export @@ -155,12 +165,12 @@ class PortSignalInterfaceItem(VHDLModel_PortSignalInterfaceItem, DOMMixin): def __init__( self, node: Iir, - identifier: str, + identifiers: List[str], mode: Mode, subtype: SubtypeOrSymbol, - defaultExpression: Expression = None, + defaultExpression: ExpressionUnion = None, ): - super().__init__(identifier, mode, subtype, defaultExpression) + super().__init__(identifiers, mode, subtype, defaultExpression) DOMMixin.__init__(self, node) @classmethod @@ -176,7 +186,15 @@ class PortSignalInterfaceItem(VHDLModel_PortSignalInterfaceItem, DOMMixin): else None ) - return cls(portNode, name, mode, subtypeIndication, value) + return cls( + portNode, + [ + name, + ], + mode, + subtypeIndication, + value, + ) @export @@ -186,12 +204,12 @@ class ParameterConstantInterfaceItem( def __init__( self, node: Iir, - identifier: str, + identifiers: List[str], mode: Mode, subtype: SubtypeOrSymbol, - defaultExpression: Expression = None, + defaultExpression: ExpressionUnion = None, ): - super().__init__(identifier, mode, subtype, defaultExpression) + super().__init__(identifiers, mode, subtype, defaultExpression) DOMMixin.__init__(self, node) @classmethod @@ -209,7 +227,15 @@ class ParameterConstantInterfaceItem( else None ) - return cls(parameterNode, name, mode, subtypeIndication, value) + return cls( + parameterNode, + [ + name, + ], + mode, + subtypeIndication, + value, + ) @export @@ -219,12 +245,12 @@ class ParameterVariableInterfaceItem( def __init__( self, node: Iir, - identifier: str, + identifiers: List[str], mode: Mode, subtype: SubtypeOrSymbol, - defaultExpression: Expression = None, + defaultExpression: ExpressionUnion = None, ): - super().__init__(identifier, mode, subtype, defaultExpression) + super().__init__(identifiers, mode, subtype, defaultExpression) DOMMixin.__init__(self, node) @classmethod @@ -242,7 +268,15 @@ class ParameterVariableInterfaceItem( else None ) - return cls(parameterNode, name, mode, subtypeIndication, value) + return cls( + parameterNode, + [ + name, + ], + mode, + subtypeIndication, + value, + ) @export @@ -250,12 +284,12 @@ class ParameterSignalInterfaceItem(VHDLModel_ParameterSignalInterfaceItem, DOMMi def __init__( self, node: Iir, - identifier: str, + identifiers: List[str], mode: Mode, subtype: SubtypeOrSymbol, - defaultExpression: Expression = None, + defaultExpression: ExpressionUnion = None, ): - super().__init__(identifier, mode, subtype, defaultExpression) + super().__init__(identifiers, mode, subtype, defaultExpression) DOMMixin.__init__(self, node) @classmethod @@ -273,7 +307,15 @@ class ParameterSignalInterfaceItem(VHDLModel_ParameterSignalInterfaceItem, DOMMi else None ) - return cls(parameterNode, name, mode, subtypeIndication, value) + return cls( + parameterNode, + [ + name, + ], + mode, + subtypeIndication, + value, + ) @export @@ -281,10 +323,10 @@ class ParameterFileInterfaceItem(VHDLModel_ParameterFileInterfaceItem, DOMMixin) def __init__( self, node: Iir, - identifier: str, + identifiers: List[str], subtype: SubtypeOrSymbol, ): - super().__init__(identifier, subtype) + super().__init__(identifiers, subtype) DOMMixin.__init__(self, node) @classmethod @@ -294,4 +336,10 @@ class ParameterFileInterfaceItem(VHDLModel_ParameterFileInterfaceItem, DOMMixin) parameterNode, "parameter", name ) - return cls(parameterNode, name, subtypeIndication) + return cls( + parameterNode, + [ + name, + ], + subtypeIndication, + ) diff --git a/pyGHDL/dom/Literal.py b/pyGHDL/dom/Literal.py index 784039d45..26be52ec8 100644 --- a/pyGHDL/dom/Literal.py +++ b/pyGHDL/dom/Literal.py @@ -9,7 +9,7 @@ # Authors: # Patrick Lehmann # -# Package module: DOM: Interface items (e.g. generic or port) +# Package module: DOM: Literals. # # License: # ============================================================================ @@ -32,7 +32,7 @@ # ============================================================================ from pydecor import export -from pyVHDLModel.VHDLModel import ( +from pyVHDLModel.SyntaxModel import ( NullLiteral as VHDLModel_NullLiteral, EnumerationLiteral as VHDLModel_EnumerationLiteral, IntegerLiteral as VHDLModel_IntegerLiteral, @@ -42,7 +42,7 @@ from pyVHDLModel.VHDLModel import ( CharacterLiteral as VHDLModel_CharacterLiteral, StringLiteral as VHDLModel_StringLiteral, ) -from pyGHDL.libghdl import name_table +from pyGHDL.libghdl import name_table, str_table from pyGHDL.libghdl._types import Iir from pyGHDL.libghdl.vhdl import nodes from pyGHDL.dom import DOMMixin @@ -149,6 +149,10 @@ class StringLiteral(VHDLModel_StringLiteral, DOMMixin): @classmethod def parse(cls, literalNode: Iir) -> "StringLiteral": - stringID = nodes.Get_String8_Id(literalNode) - value = name_table.Get_Name_Ptr(stringID) - return cls(literalNode, value) + if nodes.Get_Bit_String_Base(literalNode) is nodes.NumberBaseType.Base_None: + value = str_table.Get_String8_Ptr( + nodes.Get_String8_Id(literalNode), nodes.Get_String_Length(literalNode) + ) + return cls(literalNode, value) + else: + print("[NOT IMPLEMENTED] Bit String Literal not supported yet") diff --git a/pyGHDL/dom/Misc.py b/pyGHDL/dom/Misc.py index b80c64a82..ddd31040a 100644 --- a/pyGHDL/dom/Misc.py +++ b/pyGHDL/dom/Misc.py @@ -37,12 +37,12 @@ """ from pydecor import export -from pyVHDLModel.VHDLModel import ( +from pyVHDLModel.SyntaxModel import ( Alias as VHDLModel_Alias, ) from pyGHDL.libghdl._types import Iir -from pyGHDL.dom._Utils import GetNameOfNode from pyGHDL.dom import DOMMixin +from pyGHDL.dom._Utils import GetNameOfNode __all__ = [] diff --git a/pyGHDL/dom/Names.py b/pyGHDL/dom/Names.py index e09294d40..acb9cd1d6 100644 --- a/pyGHDL/dom/Names.py +++ b/pyGHDL/dom/Names.py @@ -32,10 +32,9 @@ # ============================================================================ from typing import List -from pyGHDL.libghdl._types import Iir from pydecor import export -from pyVHDLModel.VHDLModel import ( +from pyVHDLModel.SyntaxModel import ( SimpleName as VHDLModel_SimpleName, ParenthesisName as VHDLModel_ParenthesisName, IndexedName as VHDLModel_IndexedName, @@ -43,8 +42,10 @@ from pyVHDLModel.VHDLModel import ( SelectedName as VHDLModel_SelectedName, AttributeName as VHDLModel_AttributeName, AllName as VHDLModel_AllName, + OpenName as VHDLModel_OpenName, Name, ) +from pyGHDL.libghdl._types import Iir from pyGHDL.dom import DOMMixin __all__ = [] @@ -97,3 +98,10 @@ class AllName(VHDLModel_AllName, DOMMixin): def __init__(self, node: Iir, prefix: Name): super().__init__(prefix) DOMMixin.__init__(self, node) + + +@export +class OpenName(VHDLModel_OpenName, DOMMixin): + def __init__(self, node: Iir): + super().__init__() + DOMMixin.__init__(self, node) diff --git a/pyGHDL/dom/NonStandard.py b/pyGHDL/dom/NonStandard.py index bf48db900..1cd98b4fa 100644 --- a/pyGHDL/dom/NonStandard.py +++ b/pyGHDL/dom/NonStandard.py @@ -42,8 +42,8 @@ from typing import Any from pydecor import export -from pyGHDL.dom.PSL import VerificationUnit, VerificationProperty, VerificationMode -from pyVHDLModel.VHDLModel import ( +from pyGHDL.dom.Names import SimpleName +from pyVHDLModel.SyntaxModel import ( Design as VHDLModel_Design, Library as VHDLModel_Library, Document as VHDLModel_Document, @@ -62,8 +62,8 @@ from pyGHDL.libghdl import ( files_map_editor, ) from pyGHDL.libghdl.vhdl import nodes, sem_lib, parse -from pyGHDL.dom import DOMException -from pyGHDL.dom._Utils import GetIirKindOfNode, CheckForErrors +from pyGHDL.dom import DOMException, Position +from pyGHDL.dom._Utils import GetIirKindOfNode, CheckForErrors, GetNameOfNode from pyGHDL.dom.DesignUnit import ( Entity, Architecture, @@ -72,7 +72,11 @@ from pyGHDL.dom.DesignUnit import ( Context, Configuration, PackageInstantiation, + LibraryClause, + UseClause, + ContextReference, ) +from pyGHDL.dom.PSL import VerificationUnit, VerificationProperty, VerificationMode __all__ = [] @@ -171,20 +175,45 @@ class Document(VHDLModel_Document): libraryUnit = nodes.Get_Library_Unit(unit) nodeKind = GetIirKindOfNode(libraryUnit) + contextItems = [] + contextNames = [] + context = nodes.Get_Context_Items(unit) + if context is not nodes.Null_Iir: + for item in utils.chain_iter(context): + itemKind = GetIirKindOfNode(item) + if itemKind is nodes.Iir_Kind.Library_Clause: + contextNames.append(SimpleName(item, GetNameOfNode(item))) + if nodes.Get_Has_Identifier_List(item): + continue + + contextItems.append(LibraryClause(item, contextNames)) + contextNames = [] + elif itemKind is nodes.Iir_Kind.Use_Clause: + contextItems.append(UseClause.parse(item)) + elif itemKind is nodes.Iir_Kind.Context_Reference: + contextItems.append(ContextReference.parse(item)) + else: + pos = Position.parse(item) + raise DOMException( + "Unknown context item kind '{kind}' in context at line {line}.".format( + kind=itemKind.name, line=pos.Line + ) + ) + if nodeKind == nodes.Iir_Kind.Entity_Declaration: - entity = Entity.parse(libraryUnit) + entity = Entity.parse(libraryUnit, contextItems) self.Entities.append(entity) elif nodeKind == nodes.Iir_Kind.Architecture_Body: - architecture = Architecture.parse(libraryUnit) + architecture = Architecture.parse(libraryUnit, contextItems) self.Architectures.append(architecture) elif nodeKind == nodes.Iir_Kind.Package_Declaration: - package = Package.parse(libraryUnit) + package = Package.parse(libraryUnit, contextItems) self.Packages.append(package) elif nodeKind == nodes.Iir_Kind.Package_Body: - packageBody = PackageBody.parse(libraryUnit) + packageBody = PackageBody.parse(libraryUnit, contextItems) self.PackageBodies.append(packageBody) elif nodeKind == nodes.Iir_Kind.Package_Instantiation_Declaration: @@ -196,7 +225,7 @@ class Document(VHDLModel_Document): self.Contexts.append(context) elif nodeKind == nodes.Iir_Kind.Configuration_Declaration: - configuration = Configuration.parse(libraryUnit) + configuration = Configuration.parse(libraryUnit, contextItems) self.Configurations.append(configuration) elif nodeKind == nodes.Iir_Kind.Vunit_Declaration: @@ -213,9 +242,7 @@ class Document(VHDLModel_Document): else: raise DOMException( - "Unknown design unit kind '{kindName}'({kind}).".format( - kindName=nodeKind.name, kind=nodeKind - ) + "Unknown design unit kind '{kind}'.".format(kind=nodeKind.name) ) @property diff --git a/pyGHDL/dom/Object.py b/pyGHDL/dom/Object.py index d25acb587..def09d50c 100644 --- a/pyGHDL/dom/Object.py +++ b/pyGHDL/dom/Object.py @@ -30,22 +30,22 @@ # # SPDX-License-Identifier: GPL-2.0-or-later # ============================================================================ -from typing import Union +from typing import Union, List -from pyGHDL.libghdl._types import Iir from pydecor import export -from pyVHDLModel.VHDLModel import ( +from pyVHDLModel.SyntaxModel import ( Constant as VHDLModel_Constant, DeferredConstant as VHDLModel_DeferredConstant, Variable as VHDLModel_Variable, SharedVariable as VHDLModel_SharedVariable, Signal as VHDLModel_Signal, File as VHDLModel_File, - Expression, + ExpressionUnion, SubtypeOrSymbol, ) +from pyGHDL.libghdl._types import Iir from pyGHDL.libghdl.vhdl import nodes from pyGHDL.dom import DOMMixin from pyGHDL.dom._Utils import GetNameOfNode @@ -58,11 +58,11 @@ class Constant(VHDLModel_Constant, DOMMixin): def __init__( self, node: Iir, - identifier: str, + identifiers: List[str], subtype: SubtypeOrSymbol, - defaultExpression: Expression, + defaultExpression: ExpressionUnion, ): - super().__init__(identifier, subtype, defaultExpression) + super().__init__(identifiers, subtype, defaultExpression) DOMMixin.__init__(self, node) @classmethod @@ -78,15 +78,28 @@ class Constant(VHDLModel_Constant, DOMMixin): if defaultValue != nodes.Null_Iir: defaultExpression = GetExpressionFromNode(defaultValue) - return cls(constantNode, name, subtypeIndication, defaultExpression) + return cls( + constantNode, + [ + name, + ], + subtypeIndication, + defaultExpression, + ) else: - return DeferredConstant(constantNode, name, subtypeIndication) + return DeferredConstant( + constantNode, + [ + name, + ], + subtypeIndication, + ) @export class DeferredConstant(VHDLModel_DeferredConstant, DOMMixin): - def __init__(self, node: Iir, identifier: str, subtype: SubtypeOrSymbol): - super().__init__(identifier, subtype) + def __init__(self, node: Iir, identifiers: List[str], subtype: SubtypeOrSymbol): + super().__init__(identifiers, subtype) DOMMixin.__init__(self, node) @classmethod @@ -98,7 +111,13 @@ class DeferredConstant(VHDLModel_DeferredConstant, DOMMixin): constantNode, "deferred constant", name ) - return cls(constantNode, name, subtypeIndication) + return cls( + constantNode, + [ + name, + ], + subtypeIndication, + ) @export @@ -106,11 +125,11 @@ class Variable(VHDLModel_Variable, DOMMixin): def __init__( self, node: Iir, - identifier: str, + identifiers: List[str], subtype: SubtypeOrSymbol, - defaultExpression: Expression, + defaultExpression: ExpressionUnion, ): - super().__init__(identifier, subtype, defaultExpression) + super().__init__(identifiers, subtype, defaultExpression) DOMMixin.__init__(self, node) @classmethod @@ -127,13 +146,20 @@ class Variable(VHDLModel_Variable, DOMMixin): if defaultValue != nodes.Null_Iir: defaultExpression = GetExpressionFromNode(defaultValue) - return cls(variableNode, name, subtypeIndication, defaultExpression) + return cls( + variableNode, + [ + name, + ], + subtypeIndication, + defaultExpression, + ) @export class SharedVariable(VHDLModel_SharedVariable, DOMMixin): - def __init__(self, node: Iir, identifier: str, subtype: SubtypeOrSymbol): - super().__init__(identifier, subtype) + def __init__(self, node: Iir, identifiers: List[str], subtype: SubtypeOrSymbol): + super().__init__(identifiers, subtype) DOMMixin.__init__(self, node) @classmethod @@ -143,7 +169,13 @@ class SharedVariable(VHDLModel_SharedVariable, DOMMixin): name = GetNameOfNode(variableNode) subtypeIndication = GetSubtypeIndicationFromNode(variableNode, "variable", name) - return cls(variableNode, name, subtypeIndication) + return cls( + variableNode, + [ + name, + ], + subtypeIndication, + ) @export @@ -151,11 +183,11 @@ class Signal(VHDLModel_Signal, DOMMixin): def __init__( self, node: Iir, - identifier: str, + identifiers: List[str], subtype: SubtypeOrSymbol, - defaultExpression: Expression, + defaultExpression: ExpressionUnion, ): - super().__init__(identifier, subtype, defaultExpression) + super().__init__(identifiers, subtype, defaultExpression) DOMMixin.__init__(self, node) @classmethod @@ -170,13 +202,20 @@ class Signal(VHDLModel_Signal, DOMMixin): 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, + ) @export class File(VHDLModel_File, DOMMixin): - def __init__(self, node: Iir, identifier: str, subtype: SubtypeOrSymbol): - super().__init__(identifier, subtype) + def __init__(self, node: Iir, identifiers: List[str], subtype: SubtypeOrSymbol): + super().__init__(identifiers, subtype) DOMMixin.__init__(self, node) @classmethod @@ -188,4 +227,10 @@ class File(VHDLModel_File, DOMMixin): # FIXME: handle file open stuff - return cls(fileNode, name, subtypeIndication) + return cls( + fileNode, + [ + name, + ], + subtypeIndication, + ) diff --git a/pyGHDL/dom/PSL.py b/pyGHDL/dom/PSL.py index 6c4ba76b3..95ac72082 100644 --- a/pyGHDL/dom/PSL.py +++ b/pyGHDL/dom/PSL.py @@ -39,7 +39,6 @@ This module contains all DOM classes for VHDL's design units (:class:`context <E """ -from pyGHDL.libghdl.vhdl import nodes from pydecor import export from pyVHDLModel.PSLModel import ( diff --git a/pyGHDL/dom/Range.py b/pyGHDL/dom/Range.py index ce8dfbc40..f5153e67d 100644 --- a/pyGHDL/dom/Range.py +++ b/pyGHDL/dom/Range.py @@ -32,12 +32,7 @@ # ============================================================================ from pydecor import export -from pyVHDLModel.VHDLModel import ( - Range as VHDLModel_Range, - RangeExpression as VHDLModel_RangeExpression, - Direction, - Expression, -) +from pyVHDLModel.SyntaxModel import Range as VHDLModel_Range __all__ = [] diff --git a/pyGHDL/dom/Sequential.py b/pyGHDL/dom/Sequential.py new file mode 100644 index 000000000..be4793b2a --- /dev/null +++ b/pyGHDL/dom/Sequential.py @@ -0,0 +1,555 @@ +# ============================================================================= +# ____ _ _ ____ _ _ +# _ __ _ _ / ___| | | | _ \| | __| | ___ _ __ ___ +# | '_ \| | | | | _| |_| | | | | | / _` |/ _ \| '_ ` _ \ +# | |_) | |_| | |_| | _ | |_| | |___ | (_| | (_) | | | | | | +# | .__/ \__, |\____|_| |_|____/|_____(_)__,_|\___/|_| |_| |_| +# |_| |___/ +# ============================================================================= +# Authors: +# Patrick Lehmann +# +# Package module: DOM: Sequential statements. +# +# License: +# ============================================================================ +# Copyright (C) 2019-2021 Tristan Gingold +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <gnu.org/licenses>. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ============================================================================ +from typing import Iterable + +from pydecor import export + +from pyGHDL.dom.Concurrent import ( + WaveformElement, + ParameterAssociationItem, +) # TODO: move out from concurrent? +from pyGHDL.dom.Range import Range +from pyVHDLModel.SyntaxModel import ( + IfBranch as VHDLModel_IfBranch, + ElsifBranch as VHDLModel_ElsifBranch, + ElseBranch as VHDLModel_ElseBranch, + IfStatement as VHDLModel_IfStatement, + IndexedChoice as VHDLModel_IndexedChoice, + RangedChoice as VHDLModel_RangedChoice, + OthersCase as VHDLModel_OthersCase, + Case as VHDLModel_Case, + CaseStatement as VHDLModel_CaseStatement, + ForLoopStatement as VHDLModel_ForLoopStatement, + SequentialSimpleSignalAssignment as VHDLModel_SequentialSimpleSignalAssignment, + SequentialProcedureCall as VHDLModel_SequentialProcedureCall, + SequentialAssertStatement as VHDLModel_SequentialAssertStatement, + SequentialReportStatement as VHDLModel_SequentialReportStatement, + WaitStatement as VHDLModel_WaitStatement, + Name, + SequentialStatement, + ExpressionUnion, + SequentialChoice, + SequentialCase, +) + + +from pyGHDL.libghdl import Iir, utils +from pyGHDL.libghdl.vhdl import nodes +from pyGHDL.dom import DOMMixin, Position, DOMException +from pyGHDL.dom._Utils import GetNameOfNode + + +@export +class IfBranch(VHDLModel_IfBranch): + def __init__( + self, + branchNode: Iir, + condition: ExpressionUnion, + statements: Iterable[SequentialStatement] = None, + ): + super().__init__(condition, statements) + DOMMixin.__init__(self, branchNode) + + @classmethod + def parse(cls, branchNode: Iir, label: str) -> "IfBranch": + from pyGHDL.dom._Translate import ( + GetSequentialStatementsFromChainedNodes, + GetExpressionFromNode, + ) + + condition = GetExpressionFromNode(nodes.Get_Condition(branchNode)) + statementChain = nodes.Get_Sequential_Statement_Chain(branchNode) + statements = GetSequentialStatementsFromChainedNodes( + statementChain, "if branch", label + ) + + return cls(branchNode, condition, statements) + + +@export +class ElsifBranch(VHDLModel_ElsifBranch): + def __init__( + self, + branchNode: Iir, + condition: ExpressionUnion, + statements: Iterable[SequentialStatement] = None, + ): + super().__init__(condition, statements) + DOMMixin.__init__(self, branchNode) + + @classmethod + def parse(cls, branchNode: Iir, condition: Iir, label: str) -> "ElsifBranch": + from pyGHDL.dom._Translate import ( + GetSequentialStatementsFromChainedNodes, + GetExpressionFromNode, + ) + + condition = GetExpressionFromNode(condition) + statementChain = nodes.Get_Sequential_Statement_Chain(branchNode) + statements = GetSequentialStatementsFromChainedNodes( + statementChain, "elsif branch", label + ) + + return cls(branchNode, condition, statements) + + +@export +class ElseBranch(VHDLModel_ElseBranch): + def __init__( + self, + branchNode: Iir, + statements: Iterable[SequentialStatement] = None, + ): + super().__init__(statements) + DOMMixin.__init__(self, branchNode) + + @classmethod + def parse(cls, branchNode: Iir, label: str) -> "ElseBranch": + from pyGHDL.dom._Translate import ( + GetSequentialStatementsFromChainedNodes, + ) + + statementChain = nodes.Get_Sequential_Statement_Chain(branchNode) + statements = GetSequentialStatementsFromChainedNodes( + statementChain, "else branch", label + ) + + return cls(branchNode, statements) + + +@export +class IfStatement(VHDLModel_IfStatement, DOMMixin): + def __init__( + self, + ifNode: Iir, + ifBranch: IfBranch, + elsifBranches: Iterable[ElsifBranch] = None, + elseBranch: ElseBranch = None, + label: str = None, + ): + super().__init__(ifBranch, elsifBranches, elseBranch, label) + DOMMixin.__init__(self, ifNode) + + @classmethod + def parse(cls, ifNode: Iir, label: str) -> "IfStatement": + ifBranch = IfBranch.parse(ifNode, label) + elsifBranches = [] + elseBranch = None + # WORKAROUND: Python 3.8 syntax + # elseClause = generateNode + # while (elseClause := nodes.Get_Generate_Else_Clause(elseClause)) != nodes.Null_Iir: + elseClause = nodes.Get_Else_Clause(ifNode) + while elseClause != nodes.Null_Iir: + condition = nodes.Get_Condition(elseClause) + if condition != nodes.Null_Iir: + elsifBranches.append(ElsifBranch.parse(elseClause, condition, label)) + else: + elseBranch = ElseBranch.parse(elseClause, label) + break + + elseClause = nodes.Get_Else_Clause(elseClause) + + return cls(ifNode, ifBranch, elsifBranches, elseBranch, label) + + +@export +class IndexedChoice(VHDLModel_IndexedChoice, DOMMixin): + def __init__(self, node: Iir, expression: ExpressionUnion): + super().__init__(expression) + DOMMixin.__init__(self, node) + + +@export +class RangedChoice(VHDLModel_RangedChoice, DOMMixin): + def __init__(self, node: Iir, rng: Range): + super().__init__(rng) + DOMMixin.__init__(self, node) + + +@export +class Case(VHDLModel_Case, DOMMixin): + def __init__( + self, + node: Iir, + choices: Iterable[SequentialChoice], + statements: Iterable[SequentialStatement] = None, + ): + super().__init__(choices, statements) + DOMMixin.__init__(self, node) + + @classmethod + def parse( + cls, caseNode: Iir, choices: Iterable[SequentialChoice], label: str + ) -> "Case": + from pyGHDL.dom._Translate import GetSequentialStatementsFromChainedNodes + + statementChain = nodes.Get_Associated_Chain(caseNode) + statements = GetSequentialStatementsFromChainedNodes( + statementChain, "case", label + ) + + return cls(caseNode, choices, statements) + + +@export +class OthersCase(VHDLModel_OthersCase, DOMMixin): + def __init__( + self, + caseNode: Iir, + statements: Iterable[SequentialStatement] = None, + ): + super().__init__(statements) + DOMMixin.__init__(self, caseNode) + + @classmethod + def parse(cls, caseNode: Iir, label: str = None) -> "OthersCase": + from pyGHDL.dom._Translate import GetSequentialStatementsFromChainedNodes + + body = nodes.Get_Associated_Block(caseNode) + if body is nodes.Null_Iir: + return cls(caseNode) + + statementChain = nodes.Get_Concurrent_Statement_Chain(body) + statements = GetSequentialStatementsFromChainedNodes( + statementChain, "case others", label + ) + + return cls(caseNode, statements) + + +@export +class CaseStatement(VHDLModel_CaseStatement, DOMMixin): + def __init__( + self, + caseNode: Iir, + label: str, + expression: ExpressionUnion, + cases: Iterable[SequentialCase], + ): + super().__init__(expression, cases, label) + DOMMixin.__init__(self, caseNode) + + @classmethod + def parse(cls, caseNode: Iir, label: str) -> "CaseStatement": + from pyGHDL.dom._Utils import GetIirKindOfNode + from pyGHDL.dom._Translate import ( + GetExpressionFromNode, + GetRangeFromNode, + GetNameFromNode, + ) + + expression = GetExpressionFromNode(nodes.Get_Expression(caseNode)) + + cases = [] + choices = None + alternative = nodes.Get_Case_Statement_Alternative_Chain(caseNode) + cNode = alternative + + while alternative != nodes.Null_Iir: + choiceKind = GetIirKindOfNode(alternative) + sameAlternative = nodes.Get_Same_Alternative_Flag(alternative) + + if choiceKind in ( + nodes.Iir_Kind.Choice_By_Name, + nodes.Iir_Kind.Choice_By_Expression, + ): + choiceExpression = GetExpressionFromNode( + nodes.Get_Choice_Expression(alternative) + ) + + choice = IndexedChoice(alternative, choiceExpression) + if sameAlternative: + choices.append(choice) + alternative = nodes.Get_Chain(alternative) + continue + elif choiceKind is nodes.Iir_Kind.Choice_By_Range: + choiceRange = nodes.Get_Choice_Range(alternative) + choiceRangeKind = GetIirKindOfNode(choiceRange) + if choiceRangeKind == nodes.Iir_Kind.Range_Expression: + rng = GetRangeFromNode(choiceRange) + elif choiceRangeKind in ( + nodes.Iir_Kind.Attribute_Name, + nodes.Iir_Kind.Parenthesis_Name, + ): + rng = GetNameFromNode(choiceRange) + else: + pos = Position.parse(alternative) + raise DOMException( + "Unknown choice range kind '{kind}' in case statement at line {line}.".format( + kind=choiceRangeKind.name, line=pos.Line + ) + ) + + choice = RangedChoice(alternative, rng) + if sameAlternative: + choices.append(choice) + alternative = nodes.Get_Chain(alternative) + continue + elif choiceKind is nodes.Iir_Kind.Choice_By_Others: + if choices is not None: + cases.append(Case.parse(alternative, choices, label)) + choices = None + cases.append(OthersCase.parse(alternative, label)) + alternative = nodes.Get_Chain(alternative) + cNode = alternative + continue + else: + pos = Position.parse(alternative) + raise DOMException( + "Unknown choice kind '{kind}' in case statement at line {line}.".format( + kind=choiceKind.name, line=pos.Line + ) + ) + + if choices is not None: + cases.append(Case.parse(cNode, choices, label)) + + cNode = alternative + choices = [ + choice, + ] + + alternative = nodes.Get_Chain(alternative) + + if choices is not None: + cases.append(Case.parse(cNode, choices, label)) + + return cls(caseNode, label, expression, cases) + + +@export +class ForLoopStatement(VHDLModel_ForLoopStatement, DOMMixin): + def __init__( + self, + loopNode: Iir, + loopIndex: str, + rng: Range, + statements: Iterable[SequentialStatement] = None, + label: str = None, + ): + super().__init__(loopIndex, rng, statements, label) + DOMMixin.__init__(self, loopNode) + + @classmethod + def parse(cls, loopNode: Iir, label: str) -> "ForLoopStatement": + from pyGHDL.dom._Utils import GetIirKindOfNode + from pyGHDL.dom._Translate import ( + GetSequentialStatementsFromChainedNodes, + GetRangeFromNode, + GetNameFromNode, + ) + + spec = nodes.Get_Parameter_Specification(loopNode) + loopIndex = GetNameOfNode(spec) + + discreteRange = nodes.Get_Discrete_Range(spec) + rangeKind = GetIirKindOfNode(discreteRange) + if rangeKind == nodes.Iir_Kind.Range_Expression: + rng = GetRangeFromNode(discreteRange) + elif rangeKind in ( + nodes.Iir_Kind.Attribute_Name, + nodes.Iir_Kind.Parenthesis_Name, + ): + rng = GetNameFromNode(discreteRange) + else: + pos = Position.parse(loopNode) + raise DOMException( + "Unknown discete range kind '{kind}' in for...loop statement at line {line}.".format( + kind=rangeKind.name, line=pos.Line + ) + ) + + statementChain = nodes.Get_Sequential_Statement_Chain(loopNode) + statements = GetSequentialStatementsFromChainedNodes( + statementChain, "for", label + ) + + return cls(loopNode, loopIndex, rng, statements, label) + + +@export +class SequentialSimpleSignalAssignment( + VHDLModel_SequentialSimpleSignalAssignment, DOMMixin +): + def __init__( + self, + assignmentNode: Iir, + target: Name, + waveform: Iterable[WaveformElement], + label: str = None, + ): + super().__init__(target, waveform, label) + DOMMixin.__init__(self, assignmentNode) + + @classmethod + def parse( + cls, assignmentNode: Iir, label: str = None + ) -> "SequentialSimpleSignalAssignment": + from pyGHDL.dom._Translate import GetNameFromNode + + target = nodes.Get_Target(assignmentNode) + targetName = GetNameFromNode(target) + + waveform = [] + for wave in utils.chain_iter(nodes.Get_Waveform_Chain(assignmentNode)): + waveform.append(WaveformElement.parse(wave)) + + return cls(assignmentNode, targetName, waveform, label) + + +@export +class SequentialProcedureCall(VHDLModel_SequentialProcedureCall, DOMMixin): + def __init__( + self, + callNode: Iir, + procedureName: Name, + parameterMappings: Iterable[ParameterAssociationItem], + label: str = None, + ): + super().__init__(procedureName, parameterMappings, label) + DOMMixin.__init__(self, callNode) + + @classmethod + def parse(cls, callNode: Iir, label: str) -> "SequentialProcedureCall": + from pyGHDL.dom._Translate import GetNameFromNode, GetParameterMapAspect + + call = nodes.Get_Procedure_Call(callNode) + + prefix = nodes.Get_Prefix(call) + procedureName = GetNameFromNode(prefix) + parameterAssociations = GetParameterMapAspect( + nodes.Get_Parameter_Association_Chain(callNode) + ) + + return cls(callNode, procedureName, parameterAssociations, label) + + +@export +class SequentialAssertStatement(VHDLModel_SequentialAssertStatement, DOMMixin): + def __init__( + self, + assertNode: Iir, + condition: ExpressionUnion, + message: ExpressionUnion = None, + severity: ExpressionUnion = None, + label: str = None, + ): + super().__init__(condition, message, severity, label) + DOMMixin.__init__(self, assertNode) + + @classmethod + def parse(cls, assertNode: Iir, label: str) -> "SequentialAssertStatement": + from pyGHDL.dom._Translate import GetExpressionFromNode + + condition = GetExpressionFromNode(nodes.Get_Assertion_Condition(assertNode)) + messageNode = nodes.Get_Report_Expression(assertNode) + message = ( + None + if messageNode is nodes.Null_Iir + else GetExpressionFromNode(messageNode) + ) + severityNode = nodes.Get_Severity_Expression(assertNode) + severity = ( + None + if severityNode is nodes.Null_Iir + else GetExpressionFromNode(severityNode) + ) + + return cls(assertNode, condition, message, severity, label) + + +@export +class SequentialReportStatement(VHDLModel_SequentialReportStatement, DOMMixin): + def __init__( + self, + reportNode: Iir, + message: ExpressionUnion, + severity: ExpressionUnion = None, + label: str = None, + ): + super().__init__(message, severity, label) + DOMMixin.__init__(self, reportNode) + + @classmethod + def parse(cls, reportNode: Iir, label: str) -> "SequentialReportStatement": + from pyGHDL.dom._Translate import GetExpressionFromNode + + message = GetExpressionFromNode(nodes.Get_Report_Expression(reportNode)) + severityNode = nodes.Get_Severity_Expression(reportNode) + severity = ( + None + if severityNode is nodes.Null_Iir + else GetExpressionFromNode(severityNode) + ) + + return cls(reportNode, message, severity, label) + + +@export +class WaitStatement(VHDLModel_WaitStatement, DOMMixin): + def __init__( + self, + waitNode: Iir, + sensitivityList: Iterable[Name] = None, + condition: ExpressionUnion = None, + timeout: ExpressionUnion = None, + label: str = None, + ): + super().__init__(sensitivityList, condition, timeout, label) + DOMMixin.__init__(self, waitNode) + + @classmethod + def parse(cls, waitNode: Iir, label: str) -> "WaitStatement": + from pyGHDL.dom._Utils import GetIirKindOfNode + from pyGHDL.dom._Translate import GetExpressionFromNode + + sensitivityList = None + sensitivityListNode = nodes.Get_Sensitivity_List(waitNode) + if sensitivityListNode is not nodes.Null_Iir: + print(GetIirKindOfNode(sensitivityListNode)) + + conditionNode = nodes.Get_Condition_Clause(waitNode) + condition = ( + None + if conditionNode is nodes.Null_Iir + else GetExpressionFromNode(conditionNode) + ) + + timeoutNode = nodes.Get_Timeout_Clause(waitNode) + timeout = ( + None + if timeoutNode is nodes.Null_Iir + else GetExpressionFromNode(timeoutNode) + ) + + return cls(waitNode, sensitivityList, condition, timeout, label) diff --git a/pyGHDL/dom/Subprogram.py b/pyGHDL/dom/Subprogram.py index e8e5ebbb4..32635f693 100644 --- a/pyGHDL/dom/Subprogram.py +++ b/pyGHDL/dom/Subprogram.py @@ -34,7 +34,7 @@ from typing import List from pydecor import export -from pyVHDLModel.VHDLModel import ( +from pyVHDLModel.SyntaxModel import ( Function as VHDLModel_Function, Procedure as VHDLModel_Procedure, SubtypeOrSymbol, diff --git a/pyGHDL/dom/Symbol.py b/pyGHDL/dom/Symbol.py index 3597f2572..f52afbb18 100644 --- a/pyGHDL/dom/Symbol.py +++ b/pyGHDL/dom/Symbol.py @@ -34,14 +34,14 @@ from typing import List, Iterator from pydecor import export -from pyVHDLModel.VHDLModel import ( +from pyVHDLModel.SyntaxModel import ( EntitySymbol as VHDLModel_EntitySymbol, SimpleSubtypeSymbol as VHDLModel_SimpleSubtypeSymbol, ConstrainedScalarSubtypeSymbol as VHDLModel_ConstrainedScalarSubtypeSymbol, ConstrainedCompositeSubtypeSymbol as VHDLModel_ConstrainedCompositeSubtypeSymbol, SimpleObjectOrFunctionCallSymbol as VHDLModel_SimpleObjectOrFunctionCallSymbol, IndexedObjectOrFunctionCallSymbol as VHDLModel_IndexedObjectOrFunctionCallSymbol, - Constraint, + ConstraintUnion, Name, ) from pyGHDL.libghdl._types import Iir @@ -87,7 +87,7 @@ class ConstrainedCompositeSubtypeSymbol( VHDLModel_ConstrainedCompositeSubtypeSymbol, DOMMixin ): def __init__( - self, node: Iir, subtypeName: Name, constraints: List[Constraint] = None + self, node: Iir, subtypeName: Name, constraints: List[ConstraintUnion] = None ): super().__init__(subtypeName, constraints) DOMMixin.__init__(self, node) diff --git a/pyGHDL/dom/Type.py b/pyGHDL/dom/Type.py index efe32afc2..deb315d9d 100644 --- a/pyGHDL/dom/Type.py +++ b/pyGHDL/dom/Type.py @@ -34,7 +34,7 @@ from typing import List, Union, Iterator, Tuple from pydecor import export -from pyVHDLModel.VHDLModel import ( +from pyVHDLModel.SyntaxModel import ( AnonymousType as VHDLModel_AnonymousType, PhysicalType as VHDLModel_PhysicalType, IntegerType as VHDLModel_IntegerType, @@ -52,9 +52,8 @@ from pyVHDLModel.VHDLModel import ( ) from pyGHDL.libghdl import utils from pyGHDL.libghdl._types import Iir -from pyGHDL.libghdl.vhdl import nodes -from pyGHDL.dom import DOMMixin, DOMException -from pyGHDL.dom._Utils import GetNameOfNode, GetIirKindOfNode +from pyGHDL.libghdl.vhdl import nodes, flists +from pyGHDL.dom import DOMMixin, DOMException, Position from pyGHDL.dom.Symbol import SimpleSubtypeSymbol from pyGHDL.dom.Literal import EnumerationLiteral, PhysicalIntegerLiteral from pyGHDL.dom.Range import Range @@ -69,6 +68,8 @@ class IncompleteType(VHDLModel_AnonymousType, DOMMixin): @classmethod def parse(cls, node: Iir) -> "IncompleteType": + from pyGHDL.dom._Utils import GetNameOfNode + name = GetNameOfNode(node) return cls(node, name) @@ -113,9 +114,25 @@ class PhysicalType(VHDLModel_PhysicalType, DOMMixin): @classmethod def parse(cls, typeName: str, typeDefinitionNode: Iir) -> "PhysicalType": - from pyGHDL.dom._Translate import GetRangeFromNode - - rng = GetRangeFromNode(nodes.Get_Range_Constraint(typeDefinitionNode)) + from pyGHDL.dom._Utils import GetIirKindOfNode, GetNameOfNode + from pyGHDL.dom._Translate import GetRangeFromNode, GetNameFromNode + + rangeConstraint = nodes.Get_Range_Constraint(typeDefinitionNode) + rangeKind = GetIirKindOfNode(rangeConstraint) + if rangeKind == nodes.Iir_Kind.Range_Expression: + rng = GetRangeFromNode(rangeConstraint) + elif rangeKind in ( + nodes.Iir_Kind.Attribute_Name, + nodes.Iir_Kind.Parenthesis_Name, + ): + rng = GetNameFromNode(rangeConstraint) + else: + pos = Position.parse(typeDefinitionNode) + raise DOMException( + "Unknown range kind '{kind}' in physical type definition at line {line}.".format( + kind=rangeKind.name, line=pos.Line + ) + ) primaryUnit = nodes.Get_Primary_Unit(typeDefinitionNode) primaryUnitName = GetNameOfNode(primaryUnit) @@ -145,6 +162,7 @@ class ArrayType(VHDLModel_ArrayType, DOMMixin): @classmethod def parse(cls, typeName: str, typeDefinitionNode: Iir) -> "ArrayType": + from pyGHDL.dom._Utils import GetIirKindOfNode from pyGHDL.dom._Translate import ( GetSimpleTypeFromNode, GetSubtypeIndicationFromIndicationNode, @@ -176,12 +194,13 @@ class ArrayType(VHDLModel_ArrayType, DOMMixin): @export class RecordTypeElement(VHDLModel_RecordTypeElement, DOMMixin): - def __init__(self, node: Iir, identifier: str, subtype: SubtypeOrSymbol): - super().__init__(identifier, subtype) + def __init__(self, node: Iir, identifiers: List[str], subtype: SubtypeOrSymbol): + super().__init__(identifiers, subtype) DOMMixin.__init__(self, node) @classmethod def parse(cls, elementDeclarationNode: Iir) -> "RecordTypeElement": + from pyGHDL.dom._Utils import GetNameOfNode from pyGHDL.dom._Translate import GetSubtypeIndicationFromNode elementName = GetNameOfNode(elementDeclarationNode) @@ -189,7 +208,13 @@ class RecordTypeElement(VHDLModel_RecordTypeElement, DOMMixin): elementDeclarationNode, "record element", elementName ) - return cls(elementDeclarationNode, elementName, elementType) + return cls( + elementDeclarationNode, + [ + elementName, + ], + elementType, + ) @export @@ -202,10 +227,36 @@ class RecordType(VHDLModel_RecordType, DOMMixin): @classmethod def parse(cls, typeName: str, typeDefinitionNode: Iir) -> "RecordType": + from pyGHDL.dom._Utils import GetNameOfNode + elements = [] elementDeclarations = nodes.Get_Elements_Declaration_List(typeDefinitionNode) - for elementDeclaration in utils.flist_iter(elementDeclarations): + + 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 + while index < elementCount: + 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)) + else: + break + index += 1 + + # The last consecutive identifiers has no Identifier_List flag + if not nodes.Get_Has_Identifier_List(nextNode): + break + else: + index += 1 + elements.append(element) return cls(typeDefinitionNode, typeName, elements) @@ -221,6 +272,8 @@ class ProtectedType(VHDLModel_ProtectedType, DOMMixin): @classmethod def parse(cls, typeName: str, typeDefinitionNode: Iir) -> "ProtectedType": + from pyGHDL.dom._Utils import GetIirKindOfNode + # FIXME: change this to a generator methods = [] for item in utils.chain_iter(nodes.Get_Declaration_Chain(typeDefinitionNode)): @@ -243,6 +296,7 @@ class ProtectedTypeBody(VHDLModel_ProtectedTypeBody, DOMMixin): @classmethod def parse(cls, protectedBodyNode: Iir) -> "ProtectedTypeBody": + from pyGHDL.dom._Utils import GetNameOfNode from pyGHDL.dom._Translate import GetDeclaredItemsFromChainedNodes typeName = GetNameOfNode(protectedBodyNode) @@ -283,6 +337,7 @@ class FileType(VHDLModel_FileType, DOMMixin): @classmethod def parse(cls, typeName: str, typeDefinitionNode: Iir) -> "FileType": + from pyGHDL.dom._Utils import GetNameOfNode designatedSubtypeMark = nodes.Get_File_Type_Mark(typeDefinitionNode) designatedSubtypeName = GetNameOfNode(designatedSubtypeMark) diff --git a/pyGHDL/dom/_Translate.py b/pyGHDL/dom/_Translate.py index fc804caf4..43c443cc1 100644 --- a/pyGHDL/dom/_Translate.py +++ b/pyGHDL/dom/_Translate.py @@ -9,7 +9,7 @@ # Authors: # Patrick Lehmann # -# Package module: DOM: Interface items (e.g. generic or port) +# Package module: DOM: IIR to *** translations. # # License: # ============================================================================ @@ -30,17 +30,23 @@ # # SPDX-License-Identifier: GPL-2.0-or-later # ============================================================================ -from typing import List, Generator +from typing import List, Generator, Type from pydecor import export -from pyGHDL.dom import Position, DOMException -from pyGHDL.dom.Object import Variable -from pyGHDL.dom.PSL import DefaultClock -from pyVHDLModel.VHDLModel import ( - Constraint, +from pyGHDL.dom.Sequential import ( + IfStatement, + ForLoopStatement, + CaseStatement, + SequentialReportStatement, + SequentialAssertStatement, + WaitStatement, + SequentialSimpleSignalAssignment, +) +from pyVHDLModel.SyntaxModel import ( + ConstraintUnion, Direction, - Expression, + ExpressionUnion, SubtypeOrSymbol, BaseType, GenericInterfaceItem, @@ -48,11 +54,15 @@ from pyVHDLModel.VHDLModel import ( ParameterInterfaceItem, ModelEntity, Name, + ConcurrentStatement, + SequentialStatement, + AssociationItem, ) -from pyGHDL.libghdl import utils +from pyGHDL.libghdl import utils, name_table from pyGHDL.libghdl._types import Iir from pyGHDL.libghdl.vhdl import nodes +from pyGHDL.dom import Position, DOMException from pyGHDL.dom._Utils import ( GetNameOfNode, GetIirKindOfNode, @@ -63,6 +73,7 @@ from pyGHDL.dom.Names import ( AttributeName, ParenthesisName, AllName, + OpenName, ) from pyGHDL.dom.Symbol import ( SimpleObjectOrFunctionCallSymbol, @@ -94,6 +105,7 @@ from pyGHDL.dom.Literal import ( PhysicalFloatingLiteral, NullLiteral, ) +from pyGHDL.dom.Object import Variable from pyGHDL.dom.Expression import ( SubtractionExpression, AdditionExpression, @@ -138,8 +150,24 @@ from pyGHDL.dom.Expression import ( MatchingLessEqualExpression, MatchingGreaterThanExpression, ) +from pyGHDL.dom.Concurrent import ( + ConcurrentBlockStatement, + EntityInstantiation, + ConfigurationInstantiation, + ComponentInstantiation, + ProcessStatement, + IfGenerateStatement, + ForGenerateStatement, + CaseGenerateStatement, + ConcurrentSimpleSignalAssignment, + ConcurrentProcedureCall, + GenericAssociationItem, + PortAssociationItem, + ParameterAssociationItem, +) from pyGHDL.dom.Subprogram import Function, Procedure from pyGHDL.dom.Misc import Alias +from pyGHDL.dom.PSL import DefaultClock __all__ = [] @@ -186,8 +214,8 @@ def GetAssociations(node: Iir) -> List: associations.append(expr) else: raise DOMException( - "Unknown association kind '{kindName}'({kind}) in array index/slice or function call '{node}'.".format( - kind=kind, kindName=kind.name, node=node + "Unknown association kind '{kind}' in array index/slice or function call '{node}'.".format( + kind=kind.name, node=node ) ) @@ -197,7 +225,7 @@ def GetAssociations(node: Iir) -> List: @export def GetArrayConstraintsFromSubtypeIndication( subtypeIndication: Iir, -) -> List[Constraint]: +) -> List[ConstraintUnion]: constraints = [] for constraint in utils.flist_iter( nodes.Get_Index_Constraint_List(subtypeIndication) @@ -266,7 +294,6 @@ def GetAnonymousTypeFromNode(node: Iir) -> BaseType: typeName = GetNameOfNode(node) typeDefinition = nodes.Get_Type_Definition(node) if typeDefinition is nodes.Null_Iir: - print(1, node, typeName) return IncompleteType(node, typeName) kind = GetIirKindOfNode(typeDefinition) @@ -301,8 +328,6 @@ def GetAnonymousTypeFromNode(node: Iir) -> BaseType: @export def GetSubtypeIndicationFromNode(node: Iir, entity: str, name: str) -> SubtypeOrSymbol: subtypeIndicationNode = nodes.Get_Subtype_Indication(node) - # if subtypeIndicationNode is nodes.Null_Iir: - # return None return GetSubtypeIndicationFromIndicationNode(subtypeIndicationNode, entity, name) @@ -311,12 +336,8 @@ def GetSubtypeIndicationFromIndicationNode( subtypeIndicationNode: Iir, entity: str, name: str ) -> SubtypeOrSymbol: if subtypeIndicationNode is nodes.Null_Iir: - print( - "[NOT IMPLEMENTED]: Unhandled multiple declarations for {entity} '{name}'.".format( - entity=entity, name=name - ) - ) - return None + raise ValueError("Parameter 'subtypeIndicationNode' is 'Null_Iir'.") + kind = GetIirKindOfNode(subtypeIndicationNode) if kind in ( nodes.Iir_Kind.Simple_Name, @@ -348,9 +369,10 @@ def GetScalarConstrainedSubtypeFromNode( ) -> ConstrainedScalarSubtypeSymbol: typeMark = nodes.Get_Subtype_Type_Mark(subtypeIndicationNode) typeMarkName = GetNameOfNode(typeMark) + simpleTypeMark = SimpleName(typeMark, typeMarkName) rangeConstraint = nodes.Get_Range_Constraint(subtypeIndicationNode) r = GetRangeFromNode(rangeConstraint) - return ConstrainedScalarSubtypeSymbol(subtypeIndicationNode, typeMarkName, r) + return ConstrainedScalarSubtypeSymbol(subtypeIndicationNode, simpleTypeMark, r) @export @@ -359,10 +381,11 @@ def GetCompositeConstrainedSubtypeFromNode( ) -> ConstrainedCompositeSubtypeSymbol: typeMark = nodes.Get_Subtype_Type_Mark(subtypeIndicationNode) typeMarkName = GetNameOfNode(typeMark) + simpleTypeMark = SimpleName(typeMark, typeMarkName) constraints = GetArrayConstraintsFromSubtypeIndication(subtypeIndicationNode) return ConstrainedCompositeSubtypeSymbol( - subtypeIndicationNode, typeMarkName, constraints + subtypeIndicationNode, simpleTypeMark, constraints ) @@ -423,7 +446,7 @@ __EXPRESSION_TRANSLATION = { nodes.Iir_Kind.Less_Than_Operator: LessThanExpression, nodes.Iir_Kind.Less_Than_Or_Equal_Operator: LessEqualExpression, nodes.Iir_Kind.Greater_Than_Operator: GreaterThanExpression, - nodes.Iir_Kind.Greater_Than_Or_Equal_Operator: MatchingGreaterEqualExpression, + nodes.Iir_Kind.Greater_Than_Or_Equal_Operator: GreaterEqualExpression, nodes.Iir_Kind.Match_Equality_Operator: MatchingEqualExpression, nodes.Iir_Kind.Match_Inequality_Operator: MatchingUnequalExpression, nodes.Iir_Kind.Match_Less_Than_Operator: MatchingLessThanExpression, @@ -444,7 +467,7 @@ __EXPRESSION_TRANSLATION = { @export -def GetExpressionFromNode(node: Iir) -> Expression: +def GetExpressionFromNode(node: Iir) -> ExpressionUnion: kind = GetIirKindOfNode(node) try: @@ -475,52 +498,100 @@ def GetGenericsFromChainedNodes( GenericFunctionInterfaceItem, ) - for generic in utils.chain_iter(nodeChain): + generic = nodeChain + while generic != nodes.Null_Iir: kind = GetIirKindOfNode(generic) if kind == nodes.Iir_Kind.Interface_Constant_Declaration: from pyGHDL.dom.InterfaceItem import GenericConstantInterfaceItem - yield GenericConstantInterfaceItem.parse(generic) - elif kind == nodes.Iir_Kind.Interface_Type_Declaration: - yield GenericTypeInterfaceItem.parse(generic) - elif kind == nodes.Iir_Kind.Interface_Package_Declaration: - yield GenericPackageInterfaceItem.parse(generic) - elif kind == nodes.Iir_Kind.Interface_Procedure_Declaration: - yield GenericProcedureInterfaceItem.parse(generic) - elif kind == nodes.Iir_Kind.Interface_Function_Declaration: - yield GenericFunctionInterfaceItem.parse(generic) + 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)) + else: + generic = nextGeneric + break + + # The last consecutive identifiers has no Identifier_List flag + if not nodes.Get_Has_Identifier_List(nextGeneric): + generic = nodes.Get_Chain(nextGeneric) + break + else: + generic = nodes.Null_Iir + else: + generic = nodes.Get_Chain(generic) + + yield genericConstant + continue else: - position = Position.parse(generic) - raise DOMException( - "Unknown generic kind '{kindName}'({kind}) in generic '{generic}' at {file}:{line}:{column}.".format( - kind=kind, - kindName=kind.name, - generic=generic, - file=position.Filename, - line=position.Line, - column=position.Column, + if kind == nodes.Iir_Kind.Interface_Type_Declaration: + yield GenericTypeInterfaceItem.parse(generic) + elif kind == nodes.Iir_Kind.Interface_Package_Declaration: + yield GenericPackageInterfaceItem.parse(generic) + elif kind == nodes.Iir_Kind.Interface_Procedure_Declaration: + yield GenericProcedureInterfaceItem.parse(generic) + elif kind == nodes.Iir_Kind.Interface_Function_Declaration: + yield GenericFunctionInterfaceItem.parse(generic) + else: + position = Position.parse(generic) + raise DOMException( + "Unknown generic kind '{kind}' in generic '{generic}' at {file}:{line}:{column}.".format( + kind=kind.name, + generic=generic, + file=position.Filename, + line=position.Line, + column=position.Column, + ) ) - ) + + generic = nodes.Get_Chain(generic) @export def GetPortsFromChainedNodes( nodeChain: Iir, ) -> Generator[PortInterfaceItem, None, None]: - for port in utils.chain_iter(nodeChain): + + 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) + # Lookahead for ports with multiple identifiers at once + if nodes.Get_Has_Identifier_List(port): + nextNode = nodes.Get_Chain(port) + 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)) + else: + port = nextPort + break + + # The last consecutive identifiers has no Identifier_List flag + if not nodes.Get_Has_Identifier_List(nextPort): + port = nodes.Get_Chain(nextPort) + break + else: + port = nodes.Null_Iir + else: + port = nodes.Get_Chain(port) + yield portSignal + continue else: position = Position.parse(port) raise DOMException( - "Unknown port kind '{kindName}'({kind}) in port '{port}' at {file}:{line}:{column}.".format( - kind=kind, - kindName=kind.name, + "Unknown port kind '{kind}' in port '{port}' at {file}:{line}:{column}.".format( + kind=kind.name, port=port, file=position.Filename, line=position.Line, @@ -533,30 +604,31 @@ def GetPortsFromChainedNodes( def GetParameterFromChainedNodes( nodeChain: Iir, ) -> Generator[ParameterInterfaceItem, None, None]: - for parameter in utils.chain_iter(nodeChain): + + parameter = nodeChain + while parameter != nodes.Null_Iir: kind = GetIirKindOfNode(parameter) if kind == nodes.Iir_Kind.Interface_Constant_Declaration: from pyGHDL.dom.InterfaceItem import ParameterConstantInterfaceItem - yield ParameterConstantInterfaceItem.parse(parameter) + param = ParameterConstantInterfaceItem.parse(parameter) elif kind == nodes.Iir_Kind.Interface_Variable_Declaration: from pyGHDL.dom.InterfaceItem import ParameterVariableInterfaceItem - yield ParameterVariableInterfaceItem.parse(parameter) + param = ParameterVariableInterfaceItem.parse(parameter) elif kind == nodes.Iir_Kind.Interface_Signal_Declaration: from pyGHDL.dom.InterfaceItem import ParameterSignalInterfaceItem - yield ParameterSignalInterfaceItem.parse(parameter) + param = ParameterSignalInterfaceItem.parse(parameter) elif kind == nodes.Iir_Kind.Interface_File_Declaration: from pyGHDL.dom.InterfaceItem import ParameterFileInterfaceItem - yield ParameterFileInterfaceItem.parse(parameter) + param = ParameterFileInterfaceItem.parse(parameter) else: position = Position.parse(parameter) raise DOMException( - "Unknown parameter kind '{kindName}'({kind}) in parameter '{param}' at {file}:{line}:{column}.".format( - kind=kind, - kindName=kind.name, + "Unknown parameter kind '{kind}' in parameter '{param}' at {file}:{line}:{column}.".format( + kind=kind.name, param=parameter, file=position.Filename, line=position.Line, @@ -564,111 +636,385 @@ def GetParameterFromChainedNodes( ) ) + # Lookahead for parameters with multiple identifiers at once + if nodes.Get_Has_Identifier_List(parameter): + nextNode = nodes.Get_Chain(parameter) + 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)) + else: + parameter = nextParameter + break + + # The last consecutive identifiers has no Identifier_List flag + if not nodes.Get_Has_Identifier_List(nextParameter): + parameter = nodes.Get_Chain(nextParameter) + break + else: + parameter = nodes.Null_Iir + else: + parameter = nodes.Get_Chain(parameter) + + yield param + + +def GetMapAspect( + mapAspect: Iir, cls: Type, entity: str +) -> Generator[AssociationItem, None, None]: + for generic in utils.chain_iter(mapAspect): + kind = GetIirKindOfNode(generic) + if kind is nodes.Iir_Kind.Association_Element_By_Expression: + formalNode = nodes.Get_Formal(generic) + if formalNode is nodes.Null_Iir: + formal = None + else: + formal = GetNameFromNode(formalNode) + + actual = GetExpressionFromNode(nodes.Get_Actual(generic)) + + yield cls(generic, actual, formal) + elif kind is nodes.Iir_Kind.Association_Element_Open: + formalNode = nodes.Get_Formal(generic) + if formalNode is nodes.Null_Iir: + formal = None + else: + formal = GetNameFromNode(formalNode) + + yield cls(generic, OpenName(generic), formal) + else: + pos = Position.parse(generic) + raise DOMException( + "Unknown association kind '{kind}' in {entity} map at line {line}.".format( + kind=kind.name, entity=entity, line=pos.Line + ) + ) + + +def GetGenericMapAspect( + genericMapAspect: Iir, +) -> Generator[GenericAssociationItem, None, None]: + return GetMapAspect(genericMapAspect, GenericAssociationItem, "generic") + + +def GetPortMapAspect(portMapAspect: Iir) -> Generator[PortAssociationItem, None, None]: + return GetMapAspect(portMapAspect, PortAssociationItem, "port") + + +def GetParameterMapAspect( + parameterMapAspect: Iir, +) -> Generator[ParameterAssociationItem, None, None]: + return GetMapAspect(parameterMapAspect, ParameterAssociationItem, "parameter") + def GetDeclaredItemsFromChainedNodes( nodeChain: Iir, entity: str, name: str ) -> Generator[ModelEntity, None, None]: - for item in utils.chain_iter(nodeChain): + item = nodeChain + lastKind = None + while item != nodes.Null_Iir: kind = GetIirKindOfNode(item) if kind == nodes.Iir_Kind.Constant_Declaration: from pyGHDL.dom.Object import Constant - yield Constant.parse(item) + obj = Constant.parse(item) elif kind == nodes.Iir_Kind.Variable_Declaration: from pyGHDL.dom.Object import SharedVariable if nodes.Get_Shared_Flag(item): - yield SharedVariable.parse(item) + obj = SharedVariable.parse(item) else: - yield Variable.parse(item) - # raise DOMException("Found non-shared variable.") + obj = Variable.parse(item) elif kind == nodes.Iir_Kind.Signal_Declaration: from pyGHDL.dom.Object import Signal - yield Signal.parse(item) + obj = Signal.parse(item) elif kind == nodes.Iir_Kind.File_Declaration: from pyGHDL.dom.Object import File - yield File.parse(item) - elif kind == nodes.Iir_Kind.Type_Declaration: - yield GetTypeFromNode(item) - - elif kind == nodes.Iir_Kind.Anonymous_Type_Declaration: - yield GetAnonymousTypeFromNode(item) - - elif kind == nodes.Iir_Kind.Subtype_Declaration: - yield GetSubtypeFromNode(item) - - elif kind == nodes.Iir_Kind.Function_Declaration: - yield Function.parse(item) - - elif kind == nodes.Iir_Kind.Function_Body: - # procedureName = NodeToName(item) - print("found function body '{name}'".format(name="????")) - elif kind == nodes.Iir_Kind.Procedure_Declaration: - yield Procedure.parse(item) - elif kind == nodes.Iir_Kind.Procedure_Body: - # procedureName = NodeToName(item) - print("found procedure body '{name}'".format(name="????")) - elif kind == nodes.Iir_Kind.Protected_Type_Body: - yield ProtectedTypeBody.parse(item) - elif kind == nodes.Iir_Kind.Object_Alias_Declaration: - yield GetAliasFromNode(item) - elif kind == nodes.Iir_Kind.Component_Declaration: - from pyGHDL.dom.DesignUnit import Component - - yield Component.parse(item) - elif kind == nodes.Iir_Kind.Attribute_Declaration: - from pyGHDL.dom.Attribute import Attribute - - yield Attribute.parse(item) - elif kind == nodes.Iir_Kind.Attribute_Specification: - from pyGHDL.dom.Attribute import AttributeSpecification - - yield AttributeSpecification.parse(item) - elif kind == nodes.Iir_Kind.Use_Clause: - from pyGHDL.dom.DesignUnit import UseClause - - yield UseClause.parse(item) - elif kind == nodes.Iir_Kind.Package_Declaration: - from pyGHDL.dom.DesignUnit import Package - - yield Package.parse(item) - elif kind == nodes.Iir_Kind.Package_Instantiation_Declaration: - from pyGHDL.dom.DesignUnit import PackageInstantiation - - yield PackageInstantiation.parse(item) - elif kind == nodes.Iir_Kind.Configuration_Specification: + obj = File.parse(item) + else: + if kind == nodes.Iir_Kind.Type_Declaration: + yield GetTypeFromNode(item) + + elif kind == nodes.Iir_Kind.Anonymous_Type_Declaration: + yield GetAnonymousTypeFromNode(item) + + elif kind == nodes.Iir_Kind.Subtype_Declaration: + yield GetSubtypeFromNode(item) + + elif kind == nodes.Iir_Kind.Function_Declaration: + if nodes.Get_Has_Body(item): + yield Function.parse(item) + else: + print("[NOT IMPLEMENTED] function declaration without body") + + lastKind = kind + item = nodes.Get_Chain(item) + continue + elif kind == nodes.Iir_Kind.Function_Body: + if lastKind is nodes.Iir_Kind.Function_Declaration: + pass + else: + position = Position.parse(item) + raise DOMException( + "Found unexpected function body '{functionName}' in {entity} '{name}' at {file}:{line}:{column}.".format( + functionName=GetNameOfNode(item), + entity=entity, + name=name, + file=position.Filename, + line=position.Line, + column=position.Column, + ) + ) + elif kind == nodes.Iir_Kind.Procedure_Declaration: + if nodes.Get_Has_Body(item): + yield Procedure.parse(item) + else: + print("[NOT IMPLEMENTED] procedure declaration without body") + + lastKind = kind + item = nodes.Get_Chain(item) + continue + elif kind == nodes.Iir_Kind.Procedure_Body: + if lastKind is nodes.Iir_Kind.Procedure_Declaration: + pass + else: + position = Position.parse(item) + raise DOMException( + "Found unexpected procedure body '{functionName}' in {entity} '{name}' at {file}:{line}:{column}.".format( + functionName=GetNameOfNode(item), + entity=entity, + name=name, + file=position.Filename, + line=position.Line, + column=position.Column, + ) + ) + elif kind == nodes.Iir_Kind.Protected_Type_Body: + yield ProtectedTypeBody.parse(item) + elif kind == nodes.Iir_Kind.Object_Alias_Declaration: + yield GetAliasFromNode(item) + elif kind == nodes.Iir_Kind.Component_Declaration: + from pyGHDL.dom.DesignUnit import Component + + yield Component.parse(item) + elif kind == nodes.Iir_Kind.Attribute_Declaration: + from pyGHDL.dom.Attribute import Attribute + + yield Attribute.parse(item) + elif kind == nodes.Iir_Kind.Attribute_Specification: + from pyGHDL.dom.Attribute import AttributeSpecification + + yield AttributeSpecification.parse(item) + elif kind == nodes.Iir_Kind.Use_Clause: + from pyGHDL.dom.DesignUnit import UseClause + + yield UseClause.parse(item) + elif kind == nodes.Iir_Kind.Package_Declaration: + from pyGHDL.dom.DesignUnit import Package + + yield Package.parse(item, None) # TODO: Can it have a context? + elif kind == nodes.Iir_Kind.Package_Instantiation_Declaration: + from pyGHDL.dom.DesignUnit import PackageInstantiation + + yield PackageInstantiation.parse(item) + elif kind == nodes.Iir_Kind.Configuration_Specification: + print( + "[NOT IMPLEMENTED] Configuration specification in {name}".format( + name=name + ) + ) + elif kind == nodes.Iir_Kind.Psl_Default_Clock: + yield DefaultClock.parse(item) + elif kind == nodes.Iir_Kind.Group_Declaration: + print("[NOT IMPLEMENTED] Group declaration in {name}".format(name=name)) + elif kind == nodes.Iir_Kind.Group_Template_Declaration: + print( + "[NOT IMPLEMENTED] Group template declaration in {name}".format( + name=name + ) + ) + elif kind == nodes.Iir_Kind.Disconnection_Specification: + print( + "[NOT IMPLEMENTED] Disconnect specification in {name}".format( + name=name + ) + ) + else: + position = Position.parse(item) + raise DOMException( + "Unknown declared item kind '{kind}' in {entity} '{name}' at {file}:{line}:{column}.".format( + kind=kind.name, + entity=entity, + name=name, + file=position.Filename, + line=position.Line, + column=position.Column, + ) + ) + + lastKind = None + item = nodes.Get_Chain(item) + continue + + # Lookahead for objects with multiple identifiers at once + if nodes.Get_Has_Identifier_List(item): + nextNode = nodes.Get_Chain(item) + 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)) + else: + item = nextItem + break + + # The last consecutive identifiers has no Identifier_List flag + if not nodes.Get_Has_Identifier_List(nextItem): + item = nodes.Get_Chain(nextItem) + break + else: + item = nodes.Null_Iir + else: + item = nodes.Get_Chain(item) + + yield obj + + +def GetConcurrentStatementsFromChainedNodes( + nodeChain: Iir, entity: str, name: str +) -> Generator[ConcurrentStatement, None, None]: + for statement in utils.chain_iter(nodeChain): + label = nodes.Get_Label(statement) + label = name_table.Get_Name_Ptr(label) if label != nodes.Null_Iir else None + + pos = Position.parse(statement) + + kind = GetIirKindOfNode(statement) + if kind == nodes.Iir_Kind.Sensitized_Process_Statement: + yield ProcessStatement.parse(statement, label, True) + + elif kind == nodes.Iir_Kind.Process_Statement: + yield ProcessStatement.parse(statement, label, False) + + elif kind == nodes.Iir_Kind.Concurrent_Simple_Signal_Assignment: + yield ConcurrentSimpleSignalAssignment.parse(statement, label) + elif kind == nodes.Iir_Kind.Concurrent_Conditional_Signal_Assignment: + print( + "[NOT IMPLEMENTED] Concurrent (conditional) signal assignment (label: '{label}') at line {line}".format( + label=label, line=pos.Line + ) + ) + elif kind == nodes.Iir_Kind.Concurrent_Selected_Signal_Assignment: + print( + "[NOT IMPLEMENTED] Concurrent (selected) signal assignment (label: '{label}') at line {line}".format( + label=label, line=pos.Line + ) + ) + elif kind == nodes.Iir_Kind.Concurrent_Procedure_Call_Statement: + yield ConcurrentProcedureCall.parse(statement, label) + elif kind == nodes.Iir_Kind.Component_Instantiation_Statement: + instantiatedUnit = nodes.Get_Instantiated_Unit(statement) + instantiatedUnitKind = GetIirKindOfNode(instantiatedUnit) + if instantiatedUnitKind == nodes.Iir_Kind.Entity_Aspect_Entity: + yield EntityInstantiation.parse(statement, instantiatedUnit, label) + elif instantiatedUnitKind == nodes.Iir_Kind.Entity_Aspect_Configuration: + yield ConfigurationInstantiation.parse( + statement, instantiatedUnit, label + ) + elif instantiatedUnitKind == nodes.Iir_Kind.Simple_Name: + yield ComponentInstantiation.parse(statement, instantiatedUnit, label) + else: + raise DOMException( + "Unknown instantiation kind '{kind}' in instantiation of label {label} at {file}:{line}:{column}.".format( + kind=instantiatedUnitKind.name, + label=label, + file=pos.Filename, + line=pos.Line, + column=pos.Column, + ) + ) + elif kind == nodes.Iir_Kind.Block_Statement: + yield ConcurrentBlockStatement.parse(statement, label) + elif kind == nodes.Iir_Kind.If_Generate_Statement: + yield IfGenerateStatement.parse(statement, label) + elif kind == nodes.Iir_Kind.Case_Generate_Statement: + yield CaseGenerateStatement.parse(statement, label) + elif kind == nodes.Iir_Kind.For_Generate_Statement: + yield ForGenerateStatement.parse(statement, label) + elif kind == nodes.Iir_Kind.Psl_Assert_Directive: + print( + "[NOT IMPLEMENTED] PSL assert directive (label: '{label}') at line {line}".format( + label=label, line=pos.Line + ) + ) + else: + raise DOMException( + "Unknown statement of kind '{kind}' in {entity} '{name}' at {file}:{line}:{column}.".format( + kind=kind.name, + entity=entity, + name=name, + file=pos.Filename, + line=pos.Line, + column=pos.Column, + ) + ) + + +def GetSequentialStatementsFromChainedNodes( + nodeChain: Iir, entity: str, name: str +) -> Generator[SequentialStatement, None, None]: + for statement in utils.chain_iter(nodeChain): + label = nodes.Get_Label(statement) + label = name_table.Get_Name_Ptr(label) if label != nodes.Null_Iir else None + + pos = Position.parse(statement) + kind = GetIirKindOfNode(statement) + if kind == nodes.Iir_Kind.If_Statement: + yield IfStatement.parse(statement, label) + elif kind == nodes.Iir_Kind.For_Loop_Statement: + yield ForLoopStatement.parse(statement, label) + elif kind == nodes.Iir_Kind.Case_Statement: + yield CaseStatement.parse(statement, label) + elif kind == nodes.Iir_Kind.Simple_Signal_Assignment_Statement: + yield SequentialSimpleSignalAssignment.parse(statement, label) + elif kind in ( + nodes.Iir_Kind.Variable_Assignment_Statement, + nodes.Iir_Kind.Conditional_Variable_Assignment_Statement, + ): print( - "[NOT IMPLEMENTED] Configuration specification in {name}".format( - name=name + "[NOT IMPLEMENTED] Variable assignment (label: '{label}') at line {line}".format( + label=label, line=pos.Line ) ) - elif kind == nodes.Iir_Kind.Psl_Default_Clock: - yield DefaultClock.parse(item) - elif kind == nodes.Iir_Kind.Group_Declaration: - print("[NOT IMPLEMENTED] Group declaration in {name}".format(name=name)) - elif kind == nodes.Iir_Kind.Group_Template_Declaration: + elif kind == nodes.Iir_Kind.Wait_Statement: + yield WaitStatement.parse(statement, label) + elif kind == nodes.Iir_Kind.Procedure_Call_Statement: print( - "[NOT IMPLEMENTED] Group template declaration in {name}".format( - name=name + "[NOT IMPLEMENTED] Procedure call (label: '{label}') at line {line}".format( + label=label, line=pos.Line ) ) - elif kind == nodes.Iir_Kind.Disconnection_Specification: + elif kind == nodes.Iir_Kind.Report_Statement: + yield SequentialReportStatement.parse(statement, label) + elif kind == nodes.Iir_Kind.Assertion_Statement: + yield SequentialAssertStatement.parse(statement, label) + elif kind == nodes.Iir_Kind.Null_Statement: print( - "[NOT IMPLEMENTED] Disconnect specification in {name}".format(name=name) + "[NOT IMPLEMENTED] null statement (label: '{label}') at line {line}".format( + label=label, line=pos.Line + ) ) else: - position = Position.parse(item) raise DOMException( - "Unknown declared item kind '{kind}' in {entity} '{name}' at {file}:{line}:{column}.".format( + "Unknown statement of kind '{kind}' in {entity} '{name}' at {file}:{line}:{column}.".format( kind=kind.name, entity=entity, name=name, - file=position.Filename, - line=position.Line, - column=position.Column, + file=pos.Filename, + line=pos.Line, + column=pos.Column, ) ) diff --git a/pyGHDL/dom/_Utils.py b/pyGHDL/dom/_Utils.py index 2b17d98ab..dbb39f43d 100644 --- a/pyGHDL/dom/_Utils.py +++ b/pyGHDL/dom/_Utils.py @@ -9,7 +9,7 @@ # Authors: # Patrick Lehmann # -# Package module: DOM: Interface items (e.g. generic or port) +# Package module: DOM: IIR helper functions # # License: # ============================================================================ @@ -32,12 +32,12 @@ # ============================================================================ from pydecor import export -from pyVHDLModel.VHDLModel import Mode +from pyVHDLModel.SyntaxModel import Mode -from pyGHDL.libghdl import LibGHDLException, name_table, files_map, errorout_memory +from pyGHDL.libghdl import LibGHDLException, name_table, errorout_memory +from pyGHDL.libghdl._types import Iir from pyGHDL.libghdl.vhdl import nodes from pyGHDL.libghdl.vhdl.nodes import Null_Iir -from pyGHDL.libghdl._types import Iir from pyGHDL.dom import DOMException __all__ = [] diff --git a/pyGHDL/dom/formatting/__init__.py b/pyGHDL/dom/formatting/__init__.py index e69de29bb..828756001 100644 --- a/pyGHDL/dom/formatting/__init__.py +++ b/pyGHDL/dom/formatting/__init__.py @@ -0,0 +1,32 @@ +# ============================================================================= +# ____ _ _ ____ _ _ +# _ __ _ _ / ___| | | | _ \| | __| | ___ _ __ ___ +# | '_ \| | | | | _| |_| | | | | | / _` |/ _ \| '_ ` _ \ +# | |_) | |_| | |_| | _ | |_| | |___ | (_| | (_) | | | | | | +# | .__/ \__, |\____|_| |_|____/|_____(_)__,_|\___/|_| |_| |_| +# |_| |___/ +# ============================================================================= +# Authors: +# Patrick Lehmann +# +# Package package: A package for formatters. +# +# License: +# ============================================================================ +# Copyright (C) 2019-2021 Tristan Gingold +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <gnu.org/licenses>. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ============================================================================ diff --git a/pyGHDL/dom/formatting/prettyprint.py b/pyGHDL/dom/formatting/prettyprint.py index 4d6e5dccb..6c0f06061 100644 --- a/pyGHDL/dom/formatting/prettyprint.py +++ b/pyGHDL/dom/formatting/prettyprint.py @@ -1,25 +1,51 @@ +# ============================================================================= +# ____ _ _ ____ _ _ +# _ __ _ _ / ___| | | | _ \| | __| | ___ _ __ ___ +# | '_ \| | | | | _| |_| | | | | | / _` |/ _ \| '_ ` _ \ +# | |_) | |_| | |_| | _ | |_| | |___ | (_| | (_) | | | | | | +# | .__/ \__, |\____|_| |_|____/|_____(_)__,_|\___/|_| |_| |_| +# |_| |___/ +# ============================================================================= +# Authors: +# Patrick Lehmann +# +# Package module: A pretty printer to format the DOM as a tree in text form. +# +# License: +# ============================================================================ +# Copyright (C) 2019-2021 Tristan Gingold +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <gnu.org/licenses>. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ============================================================================ from typing import List, Union from pydecor import export -from pyGHDL.dom.Attribute import Attribute, AttributeSpecification -from pyGHDL.dom.Misc import Alias -from pyGHDL.dom.PSL import DefaultClock -from pyGHDL.dom.Subprogram import Procedure -from pyGHDL.dom.Type import ( - IntegerType, - Subtype, - ArrayType, - RecordType, - AccessType, - EnumeratedType, - FileType, - ProtectedType, - ProtectedTypeBody, - PhysicalType, - IncompleteType, +from pyGHDL.dom.Concurrent import ( + ConcurrentBlockStatement, + ProcessStatement, + IfGenerateStatement, + CaseGenerateStatement, + ForGenerateStatement, + ComponentInstantiation, + ConfigurationInstantiation, + EntityInstantiation, + ConcurrentProcedureCall, ) -from pyVHDLModel.VHDLModel import ( +from pyVHDLModel.SyntaxModel import ( GenericInterfaceItem, NamedEntity, PortInterfaceItem, @@ -27,6 +53,8 @@ from pyVHDLModel.VHDLModel import ( Function, BaseType, FullType, + BaseConstant, + ConcurrentStatement, ) from pyGHDL import GHDLBaseException @@ -42,16 +70,33 @@ from pyGHDL.dom.DesignUnit import ( UseClause, PackageInstantiation, ) -from pyGHDL.dom.Object import Constant, Signal, SharedVariable, File +from pyGHDL.dom.Symbol import ( + SimpleSubtypeSymbol, + ConstrainedCompositeSubtypeSymbol, +) +from pyGHDL.dom.Type import ( + IntegerType, + Subtype, + ArrayType, + RecordType, + AccessType, + EnumeratedType, + FileType, + ProtectedType, + ProtectedTypeBody, + PhysicalType, + IncompleteType, +) from pyGHDL.dom.InterfaceItem import ( GenericConstantInterfaceItem, PortSignalInterfaceItem, GenericTypeInterfaceItem, ) -from pyGHDL.dom.Symbol import ( - SimpleSubtypeSymbol, - ConstrainedCompositeSubtypeSymbol, -) +from pyGHDL.dom.Object import Constant, Signal, SharedVariable, File +from pyGHDL.dom.Attribute import Attribute, AttributeSpecification +from pyGHDL.dom.Subprogram import Procedure +from pyGHDL.dom.Misc import Alias +from pyGHDL.dom.PSL import DefaultClock StringBuffer = List[str] @@ -74,14 +119,19 @@ class PrettyPrint: prefix = " " * level buffer.append("{prefix}Libraries:".format(prefix=prefix)) for library in design.Libraries.values(): - for line in self.formatLibrary(library, level + 1): + buffer.append( + "{prefix} - Name: {name}".format( + prefix=prefix, name=library.Identifier + ) + ) + for line in self.formatLibrary(library, level + 2): buffer.append(line) buffer.append("{prefix}Documents:".format(prefix=prefix)) for document in design.Documents: buffer.append( - "{prefix}- Path: '{doc!s}':".format(doc=document.Path, prefix=prefix) + "{prefix} - Path: '{doc!s}':".format(doc=document.Path, prefix=prefix) ) - for line in self.formatDocument(document, level + 1): + for line in self.formatDocument(document, level + 2): buffer.append(line) return buffer @@ -91,33 +141,41 @@ class PrettyPrint: prefix = " " * level buffer.append("{prefix}Entities:".format(prefix=prefix)) for entity in library.Entities: - for line in self.formatEntity(entity, level + 1): - buffer.append(line) - # buffer.append("{prefix}Architectures:".format(prefix=prefix)) - # for architecture in library.Architectures: - # for line in self.formatArchitecture(architecture, level + 1): - # buffer.append(line) + buffer.append( + "{prefix} - {name}({architectures})".format( + prefix=prefix, + name=entity.Identifier, + architectures=", ".join( + [a.Identifier for a in entity.Architectures] + ), + ) + ) buffer.append("{prefix}Packages:".format(prefix=prefix)) for package in library.Packages: if isinstance(package, Package): - gen = self.formatPackage - else: - gen = self.formatPackageInstance - - for line in gen(package, level + 1): - buffer.append(line) - # buffer.append("{prefix}PackageBodies:".format(prefix=prefix)) - # for packageBodies in library.PackageBodies: - # for line in self.formatPackageBody(packageBodies, level + 1): - # buffer.append(line) + buffer.append( + "{prefix} - {name}".format(prefix=prefix, name=package.Identifier) + ) + elif isinstance(package, PackageInstantiation): + buffer.append( + "{prefix} - {name} instantiate from {package}".format( + prefix=prefix, + name=package.Identifier, + package=package.PackageReference, + ) + ) buffer.append("{prefix}Configurations:".format(prefix=prefix)) for configuration in library.Configurations: - for line in self.formatConfiguration(configuration, level + 1): - buffer.append(line) + buffer.append( + "{prefix} - {name}".format( + prefix=prefix, name=configuration.Identifier + ) + ) buffer.append("{prefix}Contexts:".format(prefix=prefix)) for context in library.Contexts: - for line in self.formatContext(context, level + 1): - buffer.append(line) + buffer.append( + "{prefix} - {name}".format(prefix=prefix, name=context.Identifier) + ) return buffer @@ -160,7 +218,7 @@ class PrettyPrint: buffer = [] prefix = " " * level buffer.append( - "{prefix}- Name: {name} at {file}:{line}:{column}".format( + "{prefix}- Name: {name}\n{prefix} File: {file}\n{prefix} Position: {line}:{column}".format( name=entity.Identifier, prefix=prefix, file=entity.Position.Filename.name, @@ -180,6 +238,14 @@ class PrettyPrint: for item in entity.DeclaredItems: for line in self.formatDeclaredItems(item, level + 1): buffer.append(line) + buffer.append("{prefix} Statements:".format(prefix=prefix)) + for item in entity.Statements: + buffer.append("{prefix} ...".format(prefix=prefix)) + buffer.append("{prefix} Architecures:".format(prefix=prefix)) + for item in entity.Architectures: + buffer.append( + "{prefix} - {name}".format(prefix=prefix, name=item.Identifier) + ) return buffer @@ -189,7 +255,7 @@ class PrettyPrint: buffer = [] prefix = " " * level buffer.append( - "{prefix}- Name: {name} at {file}:{line}:{column}".format( + "{prefix}- Name: {name}\n{prefix} File: {file}\n{prefix} Position: {line}:{column}".format( name=architecture.Identifier, prefix=prefix, file=architecture.Position.Filename.name, @@ -206,6 +272,15 @@ class PrettyPrint: for item in architecture.DeclaredItems: for line in self.formatDeclaredItems(item, level + 2): buffer.append(line) + buffer.append("{prefix} Hierarchy:".format(prefix=prefix)) + for item in architecture.Statements: + for line in self.formatHierarchy(item, level + 2): + buffer.append(line) + buffer.append("{prefix} Statements:".format(prefix=prefix)) + for item in architecture.Statements: + buffer.append("{prefix} ...".format(prefix=prefix)) + # for line in self.formatStatements(item, level + 2): + # buffer.append(line) return buffer @@ -232,7 +307,13 @@ class PrettyPrint: buffer = [] prefix = " " * level buffer.append( - "{prefix}- Name: {name}".format(name=package.Identifier, prefix=prefix) + "{prefix}- Name: {name}\n{prefix} File: {file}\n{prefix} Position: {line}:{column}".format( + name=package.Identifier, + prefix=prefix, + file=package.Position.Filename.name, + line=package.Position.Line, + column=package.Position.Column, + ) ) buffer.append("{prefix} Declared:".format(prefix=prefix)) for item in package.DeclaredItems: @@ -307,8 +388,8 @@ class PrettyPrint: return self.formatGenericType(generic, level) else: raise PrettyPrintException( - "Unhandled generic kind for generic '{name}'.".format( - name=generic.Identifier + "Unhandled generic kind '{kind}' for generic '{name}'.".format( + kind=generic.__class__.__name__, name=generic.Identifiers[0] ) ) @@ -319,7 +400,9 @@ class PrettyPrint: return self.formatPortSignal(port, level) else: raise PrettyPrintException( - "Unhandled port kind for port '{name}'.".format(name=port.Identifier) + "Unhandled port kind '{kind}' for port '{name}'.".format( + kind=port.__class__.__name__, name=port.Identifiers[0] + ) ) def formatGenericConstant( @@ -331,10 +414,10 @@ class PrettyPrint: buffer.append( "{prefix} - {name} : {mode!s} {subtypeindication}{initialValue}".format( prefix=prefix, - name=generic.Identifier, + name=", ".join(generic.Identifiers), mode=generic.Mode, subtypeindication=self.formatSubtypeIndication( - generic.Subtype, "generic", generic.Identifier + generic.Subtype, "generic", generic.Identifiers[0] ), initialValue=self.formatInitialValue(generic), ) @@ -366,10 +449,10 @@ class PrettyPrint: buffer.append( "{prefix} - {name} : {mode!s} {subtypeindication}{initialValue}".format( prefix=prefix, - name=port.Identifier, + name=", ".join(port.Identifiers), mode=port.Mode, subtypeindication=self.formatSubtypeIndication( - port.Subtype, "port", port.Identifier + port.Subtype, "port", port.Identifiers[0] ), initialValue=self.formatInitialValue(port), ) @@ -381,24 +464,29 @@ class PrettyPrint: buffer = [] prefix = " " * level - if isinstance(item, Constant): + if isinstance(item, BaseConstant): + if isinstance(item, Constant): + default = " := {expr}".format(expr=str(item.DefaultExpression)) + else: + default = "" + buffer.append( - "{prefix}- constant {name} : {subtype} := {expr}".format( + "{prefix}- constant {name} : {subtype}{default}".format( prefix=prefix, - name=item.Identifier, + name=", ".join(item.Identifiers), subtype=self.formatSubtypeIndication( - item.Subtype, "constant", item.Identifier + item.Subtype, "constant", item.Identifiers[0] ), - expr=str(item.DefaultExpression), + default=default, ) ) elif isinstance(item, SharedVariable): buffer.append( "{prefix}- shared variable {name} : {subtype}".format( prefix=prefix, - name=item.Identifier, + name=", ".join(item.Identifiers), subtype=self.formatSubtypeIndication( - item.Subtype, "shared variable", item.Identifier + item.Subtype, "shared variable", item.Identifiers[0] ), ) ) @@ -406,9 +494,9 @@ class PrettyPrint: buffer.append( "{prefix}- signal {name} : {subtype}{initValue}".format( prefix=prefix, - name=item.Identifier, + name=", ".join(item.Identifiers), subtype=self.formatSubtypeIndication( - item.Subtype, "signal", item.Identifier + item.Subtype, "signal", item.Identifiers[0] ), initValue=" := {expr}".format(expr=str(item.DefaultExpression)) if item.DefaultExpression is not None @@ -419,9 +507,9 @@ class PrettyPrint: buffer.append( "{prefix}- File {name} : {subtype}".format( prefix=prefix, - name=item.Identifier, + name=", ".join(item.Identifiers), subtype=self.formatSubtypeIndication( - item.Subtype, "file", item.Identifier + item.Subtype, "file", item.Identifiers[0] ), ) ) @@ -477,7 +565,9 @@ class PrettyPrint: ) elif isinstance(item, UseClause): buffer.append( - "{prefix}- use {name!s}".format(prefix=prefix, name=item.Item) + "{prefix}- use {names}".format( + prefix=prefix, names=", ".join([str(n) for n in item.Names]) + ) ) elif isinstance(item, Package): buffer.append( @@ -558,3 +648,109 @@ class PrettyPrint: return "" return " := {expr!s}".format(expr=item.DefaultExpression) + + def formatHierarchy( + self, statement: ConcurrentStatement, level: int = 0 + ) -> StringBuffer: + buffer = [] + prefix = " " * level + + if isinstance(statement, ProcessStatement): + buffer.append( + "{prefix}- {label}: process(...)".format( + prefix=prefix, label=statement.Label + ) + ) + elif isinstance(statement, EntityInstantiation): + buffer.append( + "{prefix}- {label}: entity {name}".format( + prefix=prefix, label=statement.Label, name=statement.Entity + ) + ) + elif isinstance(statement, ComponentInstantiation): + buffer.append( + "{prefix}- {label}: component {name}".format( + prefix=prefix, label=statement.Label, name=statement.Component + ) + ) + elif isinstance(statement, ConfigurationInstantiation): + buffer.append( + "{prefix}- {label}: configuration {name}".format( + prefix=prefix, label=statement.Label, name=statement.Configuration + ) + ) + elif isinstance(statement, ConcurrentBlockStatement): + buffer.append( + "{prefix}- {label}: block".format(prefix=prefix, label=statement.Label) + ) + for stmt in statement.Statements: + for line in self.formatHierarchy(stmt, level + 2): + buffer.append(line) + elif isinstance(statement, IfGenerateStatement): + buffer.append( + "{prefix}- {label}: if {condition} generate".format( + prefix=prefix, + label=statement.Label, + condition=statement.IfBranch.Condition, + ) + ) + for stmt in statement.IfBranch.Statements: + for line in self.formatHierarchy(stmt, level + 2): + buffer.append(line) + for elsifBranch in statement.ElsifBranches: + buffer.append( + "{prefix} {label}: elsif {condition} generate".format( + prefix=prefix, + label=statement.Label, + condition=elsifBranch.Condition, + ) + ) + for stmt in elsifBranch.Statements: + for line in self.formatHierarchy(stmt, level + 2): + buffer.append(line) + if statement.ElseBranch is not None: + buffer.append( + "{prefix} {label}: else generate".format( + prefix=prefix, label=statement.Label + ) + ) + for stmt in statement.ElseBranch.Statements: + for line in self.formatHierarchy(stmt, level + 2): + buffer.append(line) + elif isinstance(statement, CaseGenerateStatement): + buffer.append( + "{prefix}- {label}: case {expression} generate".format( + prefix=prefix, + label=statement.Label, + expression=statement.SelectExpression, + ) + ) + for case in statement.Cases: + buffer.append( + "{prefix} {case!s}".format( + prefix=prefix, label=case.Label, case=case + ) + ) + for stmt in case.Statements: + for line in self.formatHierarchy(stmt, level + 2): + buffer.append(line) + elif isinstance(statement, ForGenerateStatement): + buffer.append( + "{prefix}- {label}: for {index} in {range} generate".format( + prefix=prefix, + label=statement.Label, + index=statement.LoopIndex, + range=statement.Range, + ) + ) + for stmt in statement.Statements: + for line in self.formatHierarchy(stmt, level + 2): + buffer.append(line) + elif isinstance(statement, ConcurrentProcedureCall): + buffer.append( + "{prefix}- {label}: {name!s}(...)".format( + prefix=prefix, label=statement.Label, name=statement.Procedure + ) + ) + + return buffer diff --git a/pyGHDL/dom/requirements.txt b/pyGHDL/dom/requirements.txt index 66e3025ae..d296f0e96 100644 --- a/pyGHDL/dom/requirements.txt +++ b/pyGHDL/dom/requirements.txt @@ -1,4 +1,4 @@ -r ../libghdl/requirements.txt -pyVHDLModel==0.11.1 +pyVHDLModel==0.11.5 #https://github.com/VHDL/pyVHDLModel/archive/dev.zip#pyVHDLModel |