Source code for pyGHDL.dom.Configuration

# =============================================================================
#               ____ _   _ ____  _          _
#  _ __  _   _ / ___| | | |  _ \| |      __| | ___  _ __ ___
# | '_ \| | | | |  _| |_| | | | | |     / _` |/ _ \| '_ ` _ \
# | |_) | |_| | |_| |  _  | |_| | |___ | (_| | (_) | | | | | |
# | .__/ \__, |\____|_| |_|____/|_____(_)__,_|\___/|_| |_| |_|
# |_|    |___/
# =============================================================================
# Authors:
#   Patrick Lehmann
#
# Package module:   DOM: Configurations, block/component configurations, binding indications.
#
# License:
# ============================================================================
#  Copyright (C) 2019-2026 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 implements derived configuration classes from :mod:`pyVHDLModel.Configuration`.
"""

from typing import List, Generator, Union

from pyTooling.Decorators import export, InheritDocString

from pyVHDLModel.Symbol import Symbol, PossibleReference
from pyVHDLModel.Name import Name
from pyVHDLModel.Association import GenericAssociationItem, PortAssociationItem
from pyVHDLModel.Configuration import EntityAspect as VHDLModel_EntityAspect
from pyVHDLModel.Configuration import EntityAspectEntity as VHDLModel_EntityAspectEntity
from pyVHDLModel.Configuration import EntityAspectConfiguration as VHDLModel_EntityAspectConfiguration
from pyVHDLModel.Configuration import EntityAspectOpen as VHDLModel_EntityAspectOpen
from pyVHDLModel.Configuration import BindingIndication as VHDLModel_BindingIndication
from pyVHDLModel.Configuration import AllInstantiationList as VHDLModel_AllInstantiationList
from pyVHDLModel.Configuration import OthersInstantiationList as VHDLModel_OthersInstantiationList
from pyVHDLModel.Configuration import ComponentConfiguration as VHDLModel_ComponentConfiguration
from pyVHDLModel.Configuration import BlockConfiguration as VHDLModel_BlockConfiguration

from pyGHDL.libghdl._types import Iir
from pyGHDL.libghdl.vhdl import nodes
from pyGHDL.libghdl import utils
from pyGHDL.dom import DOMMixin, DOMException, Position
from pyGHDL.dom._Utils import GetIirKindOfNode
from pyGHDL.dom.Symbol import EntitySymbol, ArchitectureSymbol, ConfigurationSymbol, ComponentInstantiationSymbol


[docs] @export @InheritDocString(VHDLModel_EntityAspectEntity, merge=True) class EntityAspectEntity(VHDLModel_EntityAspectEntity, DOMMixin): """ This class implements a :mod:`pyGHDL.dom` object derived from :class:`pyVHDLModel.Configuration.EntityAspectEntity`. """
[docs] def __init__(self, node: Iir, entity: EntitySymbol, architecture: ArchitectureSymbol = None) -> None: """ Initializes an entity aspect naming an entity, optionally with an architecture. :param node: The IIR node this object was translated from. :param entity: Reference to the named entity. :param architecture: Reference to the selected architecture, or ``None`` if none was given. """ super().__init__(entity, architecture) DOMMixin.__init__(self, node)
[docs] @classmethod def parse(cls, entityAspectNode: Iir) -> "EntityAspectEntity": """ Translates the IIR node of the entity aspect to an :class:`EntityAspectEntity`. :param entityAspectNode: The IIR node of the entity aspect. :returns: The translated entity aspect. """ from pyGHDL.dom._Translate import GetName entityNameNode = nodes.Get_Entity_Name(entityAspectNode) entity = EntitySymbol(entityNameNode, GetName(entityNameNode)) architectureNode = nodes.Get_Architecture(entityAspectNode) architecture = ( None if architectureNode == nodes.Null_Iir else ArchitectureSymbol(architectureNode, GetName(architectureNode)) ) return cls(entityAspectNode, entity, architecture)
[docs] @export @InheritDocString(VHDLModel_EntityAspectConfiguration, merge=True) class EntityAspectConfiguration(VHDLModel_EntityAspectConfiguration, DOMMixin): """ This class implements a :mod:`pyGHDL.dom` object derived from :class:`pyVHDLModel.Configuration.EntityAspectConfiguration`. """
[docs] def __init__(self, node: Iir, configuration: ConfigurationSymbol) -> None: """ Initializes an entity aspect naming a configuration. :param node: The IIR node this object was translated from. :param configuration: Reference to the named configuration. """ super().__init__(configuration) DOMMixin.__init__(self, node)
[docs] @classmethod def parse(cls, entityAspectNode: Iir) -> "EntityAspectConfiguration": """ Translates the IIR node of the entity aspect to an :class:`EntityAspectConfiguration`. :param entityAspectNode: The IIR node of the entity aspect. :returns: The translated entity aspect. """ from pyGHDL.dom._Translate import GetName configurationNameNode = nodes.Get_Configuration_Name(entityAspectNode) configuration = ConfigurationSymbol(configurationNameNode, GetName(configurationNameNode)) return cls(entityAspectNode, configuration)
[docs] @export @InheritDocString(VHDLModel_EntityAspectOpen, merge=True) class EntityAspectOpen(VHDLModel_EntityAspectOpen, DOMMixin): """ This class implements a :mod:`pyGHDL.dom` object derived from :class:`pyVHDLModel.Configuration.EntityAspectOpen`. """
[docs] def __init__(self, node: Iir) -> None: """ Initializes an entity aspect denoting :vhdlkw:`open`. :param node: The IIR node this object was translated from. """ super().__init__() DOMMixin.__init__(self, node)
[docs] @classmethod def parse(cls, entityAspectNode: Iir) -> "EntityAspectOpen": """ Translates the IIR node of the entity aspect to an :class:`EntityAspectOpen`. :param entityAspectNode: The IIR node of the entity aspect. :returns: The translated entity aspect. """ return cls(entityAspectNode)
def GetEntityAspectFromNode(entityAspectNode: Iir) -> VHDLModel_EntityAspect: """ Translates an entity aspect to the matching :class:`~pyVHDLModel.Configuration.EntityAspect` subclass. :param entityAspectNode: The IIR node of the entity aspect. :returns: The translated entity aspect. :raises DOMException: If the entity aspect's kind is not handled. """ kind = GetIirKindOfNode(entityAspectNode) if kind == nodes.Iir_Kind.Entity_Aspect_Entity: return EntityAspectEntity.parse(entityAspectNode) elif kind == nodes.Iir_Kind.Entity_Aspect_Configuration: return EntityAspectConfiguration.parse(entityAspectNode) elif kind == nodes.Iir_Kind.Entity_Aspect_Open: return EntityAspectOpen.parse(entityAspectNode) else: position = Position.parse(entityAspectNode) raise DOMException(f"Unknown entity aspect kind '{kind.name}' at {position}.")
[docs] @export @InheritDocString(VHDLModel_BindingIndication, merge=True) class BindingIndication(VHDLModel_BindingIndication, DOMMixin): """ This class implements a :mod:`pyGHDL.dom` object derived from :class:`pyVHDLModel.Configuration.BindingIndication`. """
[docs] def __init__( self, node: Iir, entityAspect: VHDLModel_EntityAspect = None, genericAssociationItems: List[GenericAssociationItem] = None, portAssociationItems: List[PortAssociationItem] = None, ) -> None: """ Initializes a binding indication. :param node: The IIR node this object was translated from. :param entityAspect: The bound design entity, or ``None`` if not given. :param genericAssociationItems: List of all generic associations in the generic map aspect. :param portAssociationItems: List of all port associations in the port map aspect. """ super().__init__(entityAspect, genericAssociationItems, portAssociationItems) DOMMixin.__init__(self, node)
[docs] @classmethod def parse(cls, bindingIndicationNode: Iir) -> "BindingIndication": """ Translates the IIR node of the binding indication to a :class:`BindingIndication`. :param bindingIndicationNode: The IIR node of the binding indication. :returns: The translated binding indication. """ from pyGHDL.dom._Translate import GetGenericMapAspect, GetPortMapAspect entityAspectNode = nodes.Get_Entity_Aspect(bindingIndicationNode) entityAspect = None if entityAspectNode == nodes.Null_Iir else GetEntityAspectFromNode(entityAspectNode) genericAssociationItems = GetGenericMapAspect(nodes.Get_Generic_Map_Aspect_Chain(bindingIndicationNode)) portAssociationItems = GetPortMapAspect(nodes.Get_Port_Map_Aspect_Chain(bindingIndicationNode)) return cls(bindingIndicationNode, entityAspect, genericAssociationItems, portAssociationItems)
[docs] @export @InheritDocString(VHDLModel_AllInstantiationList, merge=True) class AllInstantiationList(VHDLModel_AllInstantiationList, DOMMixin): """ This class implements a :mod:`pyGHDL.dom` object derived from :class:`pyVHDLModel.Configuration.AllInstantiationList`. """
[docs] def __init__(self, node: Iir) -> None: """ Initializes an instantiation list denoting :vhdlkw:`all`. :param node: The IIR node this object was translated from. """ super().__init__() DOMMixin.__init__(self, node)
[docs] @export @InheritDocString(VHDLModel_OthersInstantiationList, merge=True) class OthersInstantiationList(VHDLModel_OthersInstantiationList, DOMMixin): """ This class implements a :mod:`pyGHDL.dom` object derived from :class:`pyVHDLModel.Configuration.OthersInstantiationList`. """
[docs] def __init__(self, node: Iir) -> None: """ Initializes an instantiation list denoting :vhdlkw:`others`. :param node: The IIR node this object was translated from. """ super().__init__() DOMMixin.__init__(self, node)
[docs] @export class ComponentConfiguration(VHDLModel_ComponentConfiguration, DOMMixin): """ .. note:: Also used for configuration specifications (``for U1 : comp use entity ...;`` declared directly in an architecture's declarative part) - GHDL represents both with the identical field structure (``Instantiation_List``, ``Component_Name``, ``Binding_Indication``). """
[docs] def __init__( self, node: Iir, instantiationList: Union[List[Name], "AllInstantiationList", "OthersInstantiationList"], componentName: ComponentInstantiationSymbol, bindingIndication: BindingIndication = None, ) -> None: """ Initializes a component configuration. :param node: The IIR node this object was translated from. :param instantiationList: The instances this configuration applies to. :param componentName: Reference to the component being configured. :param bindingIndication: The binding indication, or ``None`` if none was given. """ super().__init__(instantiationList, componentName, bindingIndication) DOMMixin.__init__(self, node)
[docs] @classmethod def parse(cls, node: Iir) -> "ComponentConfiguration": """ Translates an IIR node to a :class:`ComponentConfiguration`. :param node: The IIR node this object is translated from. :returns: The translated object. """ from pyGHDL.dom._Translate import GetName instList = nodes.Get_Instantiation_List(node) if instList == nodes.Iir_Flist_All: instantiationList = AllInstantiationList(node) elif instList == nodes.Iir_Flist_Others: instantiationList = OthersInstantiationList(node) else: instantiationList = [] for labelNode in utils.flist_iter(instList): instantiationList.append(GetName(labelNode)) componentNameNode = nodes.Get_Component_Name(node) componentName = ComponentInstantiationSymbol(componentNameNode, GetName(componentNameNode)) bindingIndicationNode = nodes.Get_Binding_Indication(node) bindingIndication = ( None if bindingIndicationNode == nodes.Null_Iir else BindingIndication.parse(bindingIndicationNode) ) return cls(node, instantiationList, componentName, bindingIndication)
[docs] @export @InheritDocString(VHDLModel_BlockConfiguration, merge=True) class BlockConfiguration(VHDLModel_BlockConfiguration, DOMMixin): """ This class implements a :mod:`pyGHDL.dom` object derived from :class:`pyVHDLModel.Configuration.BlockConfiguration`. """
[docs] def __init__( self, node: Iir, blockSpecification: Symbol, items: List[Union["BlockConfiguration", ComponentConfiguration]] = None, ) -> None: """ Initializes a block configuration. :param node: The IIR node this object was translated from. :param blockSpecification: The configured block. :param items: Nested configurations. """ super().__init__(blockSpecification, items) DOMMixin.__init__(self, node)
[docs] @classmethod def parse(cls, node: Iir) -> "BlockConfiguration": """ Translates an IIR node to a :class:`BlockConfiguration`. :param node: The IIR node this object is translated from. :returns: The translated object. """ from pyGHDL.dom._Translate import GetName from pyGHDL.dom.Symbol import Symbol as DOMSymbol blockSpecificationNode = nodes.Get_Block_Specification(node) blockSpecification = DOMSymbol( blockSpecificationNode, GetName(blockSpecificationNode), PossibleReference.Architecture | PossibleReference.Label, ) items = list(GetConfigurationItemsFromChainedNodes(nodes.Get_Configuration_Item_Chain(node))) return cls(node, blockSpecification, items)
def GetConfigurationItemsFromChainedNodes( nodeChain: Iir, ) -> Generator[Union[BlockConfiguration, ComponentConfiguration], None, None]: """ Translates a chain of configuration items to :class:`ComponentConfiguration` and :class:`BlockConfiguration`. :param nodeChain: The IIR node starting the chain of configuration items. :returns: Generator yielding the translated configuration items, in source order. :raises DOMException: If a configuration item's kind is not handled. """ for item in utils.chain_iter(nodeChain): kind = GetIirKindOfNode(item) if kind == nodes.Iir_Kind.Component_Configuration: yield ComponentConfiguration.parse(item) elif kind == nodes.Iir_Kind.Block_Configuration: yield BlockConfiguration.parse(item) else: position = Position.parse(item) raise DOMException(f"Unknown configuration item kind '{kind.name}' at {position}.")