# =============================================================================
# ____ _ _ ____ _ _
# _ __ _ _ / ___| | | | _ \| | __| | ___ _ __ ___
# | '_ \| | | | | _| |_| | | | | | / _` |/ _ \| '_ ` _ \
# | |_) | |_| | |_| | _ | |_| | |___ | (_| | (_) | | | | | |
# | .__/ \__, |\____|_| |_|____/|_____(_)__,_|\___/|_| |_| |_|
# |_| |___/
# =============================================================================
# Authors:
# Patrick Lehmann
#
# Package module: DOM: VHDL design units (e.g. context or package).
#
# License:
# ============================================================================
# Copyright (C) 2019-2022 Tristan Gingold
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# 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
# ============================================================================
"""
This module contains all DOM classes for VHDL's design units (:class:`context <Entity>`,
:class:`architecture <Architecture>`, :class:`package <Package>`,
:class:`package body <PackageBody>`, :class:`context <Context>` and
:class:`configuration <Configuration>`.
"""
from typing import Iterable
from pyTooling.Decorators import export, InheritDocString
from pyVHDLModel.Symbol import Symbol
from pyVHDLModel.Instantiation import PackageInstantiation as VHDLModel_PackageInstantiation
from pyVHDLModel.Interface import GenericInterfaceItemMixin, PortInterfaceItemMixin
from pyVHDLModel.Concurrent import ConcurrentStatement
from pyVHDLModel.DesignUnit import Context as VHDLModel_Context
from pyVHDLModel.DesignUnit import Package as VHDLModel_Package
from pyVHDLModel.DesignUnit import PackageBody as VHDLModel_PackageBody
from pyVHDLModel.DesignUnit import Entity as VHDLModel_Entity
from pyVHDLModel.DesignUnit import Architecture as VHDLModel_Architecture
from pyVHDLModel.DesignUnit import Component as VHDLModel_Component
from pyVHDLModel.DesignUnit import Configuration as VHDLModel_Configuration
from pyVHDLModel.DesignUnit import LibraryClause as VHDLModel_LibraryClause
from pyVHDLModel.DesignUnit import UseClause as VHDLModel_UseClause
from pyVHDLModel.DesignUnit import ContextReference as VHDLModel_ContextReference
from pyVHDLModel.DesignUnit import ContextUnion as VHDLModel_ContextUnion
from pyVHDLModel.Association import GenericAssociationItem as VHDLModel_GenericAssociationItem
from pyGHDL.libghdl import utils
from pyGHDL.libghdl._types import Iir
from pyGHDL.libghdl.vhdl import nodes
from pyGHDL.dom import DOMMixin, Position, DOMException
from pyGHDL.dom._Utils import GetNameOfNode, GetDocumentationOfNode
from pyGHDL.dom._Translate import GetGenericsFromChainedNodes, GetPortsFromChainedNodes, GetName, GetGenericMapAspect
from pyGHDL.dom._Translate import GetDeclaredItemsFromChainedNodes, GetConcurrentStatementsFromChainedNodes
from pyGHDL.dom.Name import SimpleName, AllName
from pyGHDL.dom.Symbol import (
EntitySymbol,
ContextReferenceSymbol,
LibraryReferenceSymbol,
PackageSymbol,
PackageReferenceSymbol,
PackageMemberReferenceSymbol,
AllPackageMembersReferenceSymbol,
)
from pyGHDL.dom.Configuration import BlockConfiguration
[docs]
@export
@InheritDocString(VHDLModel_LibraryClause, merge=True)
class LibraryClause(VHDLModel_LibraryClause, DOMMixin):
"""
This class implements a :mod:`pyGHDL.dom` object derived from :class:`pyVHDLModel.DesignUnit.LibraryClause`.
"""
[docs]
def __init__(self, libraryNode: Iir, symbols: Iterable[Symbol]) -> None:
"""
Initializes a library clause.
:param libraryNode: The IIR node of the :vhdlkw:`library` clause.
:param symbols: A list of symbols this reference references to.
"""
super().__init__(symbols, None)
DOMMixin.__init__(self, libraryNode)
[docs]
@export
@InheritDocString(VHDLModel_UseClause, merge=True)
class UseClause(VHDLModel_UseClause, DOMMixin):
"""
This class implements a :mod:`pyGHDL.dom` object derived from :class:`pyVHDLModel.DesignUnit.UseClause`.
"""
[docs]
def __init__(self, useNode: Iir, symbols: Iterable[Symbol]) -> None:
"""
Initializes a use clause.
:param useNode: The IIR node of the :vhdlkw:`use` clause.
:param symbols: A list of symbols this reference references to.
"""
super().__init__(symbols, None)
DOMMixin.__init__(self, useNode)
[docs]
@classmethod
def parse(cls, useNode: Iir):
"""
Translates the IIR node of the use clause to an :class:`UseClause`.
:param useNode: The IIR node of the use clause.
:returns: The translated use clause.
"""
nameNode = nodes.Get_Selected_Name(useNode)
name = GetName(nameNode)
if name.Prefix is name.Root:
symbolType = PackageReferenceSymbol
elif isinstance(name, AllName):
symbolType = AllPackageMembersReferenceSymbol
else:
symbolType = PackageMemberReferenceSymbol
uses = [symbolType(nameNode, name)]
for use in utils.chain_iter(nodes.Get_Use_Clause_Chain(useNode)):
nameNode = nodes.Get_Selected_Name(use)
name = GetName(nameNode)
if name.Prefix is name.Root:
symbolType = PackageReferenceSymbol
elif isinstance(name, AllName):
symbolType = AllPackageMembersReferenceSymbol
else:
symbolType = PackageMemberReferenceSymbol
uses.append(symbolType(nameNode, name))
return cls(useNode, uses)
[docs]
@export
@InheritDocString(VHDLModel_ContextReference, merge=True)
class ContextReference(VHDLModel_ContextReference, DOMMixin):
"""
This class implements a :mod:`pyGHDL.dom` object derived from :class:`pyVHDLModel.DesignUnit.ContextReference`.
"""
[docs]
def __init__(self, contextNode: Iir, symbols: Iterable[Symbol]) -> None:
"""
Initializes a context reference.
:param contextNode: The IIR node of the context reference.
:param symbols: A list of symbols this reference references to.
"""
super().__init__(symbols, None)
DOMMixin.__init__(self, contextNode)
[docs]
@classmethod
def parse(cls, contextNode: Iir):
"""
Translates the IIR node of the context to a :class:`ContextReference`.
:param contextNode: The IIR node of the context.
:returns: The translated context.
"""
nameNode = nodes.Get_Selected_Name(contextNode)
contexts = [ContextReferenceSymbol(nameNode, GetName(nameNode))]
for context in utils.chain_iter(nodes.Get_Context_Reference_Chain(contextNode)):
nameNode = nodes.Get_Selected_Name(context)
contexts.append(ContextReferenceSymbol(nameNode, GetName(nameNode)))
return cls(contextNode, contexts)
[docs]
@export
@InheritDocString(VHDLModel_Entity, merge=True)
class Entity(VHDLModel_Entity, DOMMixin):
"""
This class implements a :mod:`pyGHDL.dom` object derived from :class:`pyVHDLModel.DesignUnit.Entity`.
"""
[docs]
def __init__(
self,
node: Iir,
identifier: str,
contextItems: Iterable[VHDLModel_ContextUnion] = None,
genericItems: Iterable[GenericInterfaceItemMixin] = None,
portItems: Iterable[PortInterfaceItemMixin] = None,
declaredItems: Iterable = None,
statements: Iterable["ConcurrentStatement"] = None,
documentation: str = None,
) -> None:
"""
Initializes an entity declaration.
:param node: The IIR node this object was translated from.
:param identifier: The entity's identifier.
:param contextItems: List of all context items (library, use and context clauses).
:param genericItems: List of all generics, in declaration order.
:param portItems: List of all ports, in declaration order.
:param declaredItems: List of all declared items in this concurrent declaration region.
:param statements: List of all concurrent statements in this construct.
:param documentation: The documentation comment associated with this declaration.
"""
super().__init__(
identifier, contextItems, genericItems, portItems, declaredItems, statements, documentation, None
)
DOMMixin.__init__(self, node)
[docs]
@classmethod
def parse(cls, entityNode: Iir, contextItems: Iterable[VHDLModel_ContextUnion]):
"""
Translates the IIR node of the entity declaration to an :class:`Entity`.
:param entityNode: The IIR node of the entity declaration.
:param contextItems: List of all context items (library, use and context clauses) preceding the unit.
:returns: The translated entity declaration.
"""
name = GetNameOfNode(entityNode)
documentation = GetDocumentationOfNode(entityNode)
generics = GetGenericsFromChainedNodes(nodes.Get_Generic_Chain(entityNode))
ports = GetPortsFromChainedNodes(nodes.Get_Port_Chain(entityNode))
declaredItems = GetDeclaredItemsFromChainedNodes(nodes.Get_Declaration_Chain(entityNode), "entity", name)
statements = GetConcurrentStatementsFromChainedNodes(
nodes.Get_Concurrent_Statement_Chain(entityNode), "entity", name
)
# FIXME: read use clauses
return cls(entityNode, name, contextItems, generics, ports, declaredItems, statements, documentation)
[docs]
@export
@InheritDocString(VHDLModel_Architecture, merge=True)
class Architecture(VHDLModel_Architecture, DOMMixin):
"""
This class implements a :mod:`pyGHDL.dom` object derived from :class:`pyVHDLModel.DesignUnit.Architecture`.
"""
[docs]
def __init__(
self,
node: Iir,
identifier: str,
entity: EntitySymbol,
contextItems: Iterable[VHDLModel_ContextUnion] = None,
declaredItems: Iterable = None,
statements: Iterable["ConcurrentStatement"] = None,
documentation: str = None,
) -> None:
"""
Initializes an architecture declaration.
:param node: The IIR node this object was translated from.
:param identifier: The architecture's identifier.
:param entity: Reference to the entity this architecture implements.
:param contextItems: List of all context items (library, use and context clauses).
:param declaredItems: List of all declared items in this concurrent declaration region.
:param statements: List of all concurrent statements in this construct.
:param documentation: The documentation comment associated with this declaration.
"""
super().__init__(identifier, entity, contextItems, declaredItems, statements, documentation, None)
DOMMixin.__init__(self, node)
[docs]
@classmethod
def parse(cls, architectureNode: Iir, contextItems: Iterable[VHDLModel_ContextUnion]):
"""
Translates the IIR node of the architecture body to an :class:`Architecture`.
:param architectureNode: The IIR node of the architecture body.
:param contextItems: List of all context items (library, use and context clauses) preceding the unit.
:returns: The translated architecture body.
"""
name = GetNameOfNode(architectureNode)
documentation = GetDocumentationOfNode(architectureNode)
entityNameNode = nodes.Get_Entity_Name(architectureNode)
entitySymbol = EntitySymbol(entityNameNode, GetName(entityNameNode))
declaredItems = GetDeclaredItemsFromChainedNodes(
nodes.Get_Declaration_Chain(architectureNode), "architecture", name
)
statements = GetConcurrentStatementsFromChainedNodes(
nodes.Get_Concurrent_Statement_Chain(architectureNode), "architecture", name
)
# FIXME: read use clauses
return cls(architectureNode, name, entitySymbol, contextItems, declaredItems, statements, documentation)
[docs]
@export
@InheritDocString(VHDLModel_Component, merge=True)
class Component(VHDLModel_Component, DOMMixin):
"""
This class implements a :mod:`pyGHDL.dom` object derived from :class:`pyVHDLModel.DesignUnit.Component`.
"""
[docs]
def __init__(
self,
node: Iir,
identifier: str,
genericItems: Iterable[GenericInterfaceItemMixin] = None,
portItems: Iterable[PortInterfaceItemMixin] = None,
documentation: str = None,
) -> None:
"""
Initializes a component declaration.
:param node: The IIR node this object was translated from.
:param identifier: The component's identifier.
:param genericItems: List of all generics of this component, in declaration order.
:param portItems: List of all ports of this component, in declaration order.
:param documentation: The documentation comment associated with this declaration.
"""
super().__init__(identifier, genericItems, portItems, documentation, None)
DOMMixin.__init__(self, node)
[docs]
@classmethod
def parse(cls, componentNode: Iir):
"""
Translates the IIR node of the component declaration to a :class:`Component`.
:param componentNode: The IIR node of the component declaration.
:returns: The translated component declaration.
"""
name = GetNameOfNode(componentNode)
documentation = GetDocumentationOfNode(componentNode)
generics = GetGenericsFromChainedNodes(nodes.Get_Generic_Chain(componentNode))
ports = GetPortsFromChainedNodes(nodes.Get_Port_Chain(componentNode))
return cls(componentNode, name, generics, ports, documentation)
[docs]
@export
@InheritDocString(VHDLModel_Package, merge=True)
class Package(VHDLModel_Package, DOMMixin):
"""
This class implements a :mod:`pyGHDL.dom` object derived from :class:`pyVHDLModel.DesignUnit.Package`.
"""
[docs]
def __init__(
self,
node: Iir,
identifier: str,
contextItems: Iterable[VHDLModel_ContextUnion] = None,
genericItems: Iterable[GenericInterfaceItemMixin] = None,
declaredItems: Iterable = None,
documentation: str = None,
) -> None:
"""
Initialize a package.
:param node: The IIR node this object was translated from.
:param identifier: Name of the VHDL package.
:param contextItems: List of all context items (library, use and context clauses).
:param genericItems: List of all generics, in declaration order.
:param declaredItems: List of all declared items in this concurrent declaration region.
:param documentation: The documentation comment associated with this declaration.
"""
super().__init__(identifier, contextItems, genericItems, declaredItems, documentation, None)
DOMMixin.__init__(self, node)
[docs]
@classmethod
def parse(cls, packageNode: Iir, contextItems: Iterable[VHDLModel_ContextUnion]):
"""
Translates the IIR node of the package declaration to a :class:`Package`.
:param packageNode: The IIR node of the package declaration.
:param contextItems: List of all context items (library, use and context clauses) preceding the unit.
:returns: The translated package declaration.
"""
name = GetNameOfNode(packageNode)
documentation = GetDocumentationOfNode(packageNode)
packageHeader = nodes.Get_Package_Header(packageNode)
if packageHeader is not nodes.Null_Iir:
generics = GetGenericsFromChainedNodes(nodes.Get_Generic_Chain(packageHeader))
else:
generics = []
declaredItems = GetDeclaredItemsFromChainedNodes(nodes.Get_Declaration_Chain(packageNode), "package", name)
# FIXME: read use clauses
return cls(packageNode, name, contextItems, generics, declaredItems, documentation)
[docs]
@export
@InheritDocString(VHDLModel_PackageBody, merge=True)
class PackageBody(VHDLModel_PackageBody, DOMMixin):
"""
This class implements a :mod:`pyGHDL.dom` object derived from :class:`pyVHDLModel.DesignUnit.PackageBody`.
"""
[docs]
def __init__(
self,
node: Iir,
packageSymbol: PackageSymbol,
contextItems: Iterable[VHDLModel_ContextUnion] = None,
declaredItems: Iterable = None,
documentation: str = None,
) -> None:
"""
Initializes a package body declaration.
:param node: The IIR node this object was translated from.
:param packageSymbol: Reference to the package this body implements.
:param contextItems: List of all context items (library, use and context clauses).
:param declaredItems: List of all declared items in this concurrent declaration region.
:param documentation: The documentation comment associated with this declaration.
"""
super().__init__(packageSymbol, contextItems, declaredItems, documentation, None)
DOMMixin.__init__(self, node)
[docs]
@classmethod
def parse(cls, packageBodyNode: Iir, contextItems: Iterable[VHDLModel_ContextUnion]):
"""
Translates the IIR node of the package body to a :class:`PackageBody`.
:param packageBodyNode: The IIR node of the package body.
:param contextItems: List of all context items (library, use and context clauses) preceding the unit.
:returns: The translated package body.
"""
packageIdentifier = GetNameOfNode(packageBodyNode)
packageSymbol = PackageSymbol(packageBodyNode, SimpleName(packageBodyNode, packageIdentifier))
documentation = GetDocumentationOfNode(packageBodyNode)
declaredItems = GetDeclaredItemsFromChainedNodes(
nodes.Get_Declaration_Chain(packageBodyNode), "package", packageIdentifier
)
# FIXME: read use clauses
return cls(packageBodyNode, packageSymbol, contextItems, declaredItems, documentation)
[docs]
@export
@InheritDocString(VHDLModel_PackageInstantiation, merge=True)
class PackageInstantiation(VHDLModel_PackageInstantiation, DOMMixin):
"""
This class implements a :mod:`pyGHDL.dom` object derived from :class:`pyVHDLModel.Instantiation.PackageInstantiation`.
"""
[docs]
def __init__(
self,
node: Iir,
identifier: str,
uninstantiatedPackageName: Symbol,
contextItems: Iterable[VHDLModel_ContextUnion] = None,
genericAssociationItems: Iterable[VHDLModel_GenericAssociationItem] = None,
documentation: str = None,
) -> None:
"""
Initializes a package instantiation.
:param node: The IIR node this object was translated from.
:param identifier: The instantiated package's identifier.
:param uninstantiatedPackageName: The name of the uninstantiated generic package.
:param contextItems: List of all context items (library, use and context clauses).
:param genericAssociationItems: List of all generic associations in the generic map aspect.
:param documentation: The documentation comment associated with this declaration.
"""
super().__init__(identifier, uninstantiatedPackageName, contextItems, genericAssociationItems, documentation)
DOMMixin.__init__(self, node)
[docs]
@classmethod
def parse(cls, packageNode: Iir, contextItems: Iterable[VHDLModel_ContextUnion] = None):
"""
Translates the IIR node of the package declaration to a :class:`PackageInstantiation`.
:param packageNode: The IIR node of the package declaration.
:param contextItems: List of all context items (library, use and context clauses) preceding the unit.
:returns: The translated package declaration.
"""
name = GetNameOfNode(packageNode)
documentation = GetDocumentationOfNode(packageNode)
uninstantiatedPackageName = GetName(
uninstantiatedPackageNode := nodes.Get_Uninstantiated_Package_Name(packageNode)
)
uninstantiatedPackageSymbol = PackageReferenceSymbol(uninstantiatedPackageNode, uninstantiatedPackageName)
genericAssociationItems = GetGenericMapAspect(nodes.Get_Generic_Map_Aspect_Chain(packageNode))
return cls(packageNode, name, uninstantiatedPackageSymbol, contextItems, genericAssociationItems, documentation)
[docs]
@export
@InheritDocString(VHDLModel_Context, merge=True)
class Context(VHDLModel_Context, DOMMixin):
"""
This class implements a :mod:`pyGHDL.dom` object derived from :class:`pyVHDLModel.DesignUnit.Context`.
"""
[docs]
def __init__(
self,
node: Iir,
identifier: str,
references: Iterable[VHDLModel_ContextUnion] = None,
documentation: str = None,
) -> None:
"""
Initializes a context declaration.
:param node: The IIR node this object was translated from.
:param identifier: The context's identifier.
:param references: All context items, in declaration order.
:param documentation: The documentation comment associated with this declaration.
"""
super().__init__(identifier, references, documentation, None)
DOMMixin.__init__(self, node)
[docs]
@classmethod
def parse(cls, contextNode: Iir):
"""
Translates the IIR node of the context to a :class:`Context`.
:param contextNode: The IIR node of the context.
:returns: The translated context.
"""
from pyGHDL.dom._Utils import GetIirKindOfNode
name = GetNameOfNode(contextNode)
documentation = GetDocumentationOfNode(contextNode)
items = []
names = []
for item in utils.chain_iter(nodes.Get_Context_Items(contextNode)):
kind = GetIirKindOfNode(item)
if kind is nodes.Iir_Kind.Library_Clause:
libraryIdentifier = GetNameOfNode(item)
names.append(LibraryReferenceSymbol(item, SimpleName(item, libraryIdentifier)))
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))
elif kind is nodes.Iir_Kind.Context_Reference:
items.append(ContextReference.parse(item))
else:
pos = Position.parse(item)
raise DOMException(f"Unknown context item kind '{kind.name}' in context at line {pos.Line}.")
return cls(contextNode, name, items, documentation)
[docs]
@export
@InheritDocString(VHDLModel_Configuration, merge=True)
class Configuration(VHDLModel_Configuration, DOMMixin):
"""
This class implements a :mod:`pyGHDL.dom` object derived from :class:`pyVHDLModel.DesignUnit.Configuration`.
"""
[docs]
def __init__(
self,
node: Iir,
identifier: str,
entity: EntitySymbol,
blockConfiguration: BlockConfiguration,
contextItems: Iterable[Context] = None,
documentation: str = None,
) -> None:
"""
Initializes a configuration declaration.
:param node: The IIR node this object was translated from.
:param identifier: The configuration's identifier.
:param entity: Reference to the entity this configuration configures.
:param blockConfiguration: The configuration of the entity's architecture.
:param contextItems: List of all context items (library, use and context clauses).
:param documentation: The documentation comment associated with this declaration.
"""
super().__init__(identifier, entity, blockConfiguration, contextItems, documentation, None)
DOMMixin.__init__(self, node)
[docs]
@classmethod
def parse(cls, configurationNode: Iir, contextItems: Iterable[Context]) -> "Configuration":
"""
Translates the IIR node of the configuration declaration to a :class:`Configuration`.
:param configurationNode: The IIR node of the configuration declaration.
:param contextItems: List of all context items (library, use and context clauses) preceding the unit.
:returns: The translated configuration declaration.
"""
from pyGHDL.dom._Translate import GetName
name = GetNameOfNode(configurationNode)
documentation = GetDocumentationOfNode(configurationNode)
entityNameNode = nodes.Get_Entity_Name(configurationNode)
entity = EntitySymbol(entityNameNode, GetName(entityNameNode))
blockConfiguration = BlockConfiguration.parse(nodes.Get_Block_Configuration(configurationNode))
return cls(configurationNode, name, entity, blockConfiguration, contextItems, documentation)