From 0b16ac19879a49acfe777a922dff182e18574442 Mon Sep 17 00:00:00 2001 From: Patrick Lehmann Date: Sun, 27 Dec 2020 23:27:35 +0100 Subject: Added first implementation of a document object model (DOM). --- pyGHDL/dom/Common.py | 48 +++++++++++++++++++++ pyGHDL/dom/DesignUnit.py | 100 ++++++++++++++++++++++++++++++++++++++++++++ pyGHDL/dom/InterfaceItem.py | 33 +++++++++++++++ pyGHDL/dom/Misc.py | 96 ++++++++++++++++++++++++++++++++++++++++++ pyGHDL/dom/__init__.py | 4 ++ 5 files changed, 281 insertions(+) create mode 100644 pyGHDL/dom/Common.py create mode 100644 pyGHDL/dom/DesignUnit.py create mode 100644 pyGHDL/dom/InterfaceItem.py create mode 100644 pyGHDL/dom/Misc.py create mode 100644 pyGHDL/dom/__init__.py (limited to 'pyGHDL') diff --git a/pyGHDL/dom/Common.py b/pyGHDL/dom/Common.py new file mode 100644 index 000000000..8baa6537e --- /dev/null +++ b/pyGHDL/dom/Common.py @@ -0,0 +1,48 @@ +from pydecor import export + +from pyVHDLModel.VHDLModel import Modes + +from libghdl.thin import name_table +from libghdl.thin.vhdl import nodes + +__all__ = [] +__api__ = __all__ + + +@export +class GHDLBaseException(Exception): + pass + + +@export +class LibGHDLException(GHDLBaseException): + pass + + +@export +class GHDLException(GHDLBaseException): + pass + + +@export +class GHDLMixin: + _MODE_TRANSLATION = { + nodes.Iir_Mode.In_Mode: Modes.In, + nodes.Iir_Mode.Out_Mode: Modes.Out, + nodes.Iir_Mode.Inout_Mode: Modes.InOut, + nodes.Iir_Mode.Buffer_Mode: Modes.Buffer, + nodes.Iir_Mode.Linkage_Mode: Modes.Linkage + } + + @classmethod + def _ghdlNodeToName(cls, node): + """Return the python string from node :param:`node` identifier""" + return name_table.Get_Name_Ptr(nodes.Get_Identifier(node)).decode("utf-8") + + @classmethod + def _ghdlPortToMode(cls, port): + """Return the mode of a port.""" + try: + return cls._MODE_TRANSLATION[nodes.Get_Mode(port)] + except KeyError: + raise LibGHDLException("Unknown mode.") diff --git a/pyGHDL/dom/DesignUnit.py b/pyGHDL/dom/DesignUnit.py new file mode 100644 index 000000000..894651c2c --- /dev/null +++ b/pyGHDL/dom/DesignUnit.py @@ -0,0 +1,100 @@ +from pydecor import export + +from pyVHDLModel.VHDLModel import Entity as VHDLModel_Entity +from pyVHDLModel.VHDLModel import Architecture as VHDLModel_Architecture +from pyVHDLModel.VHDLModel import Package as VHDLModel_Package +from pyVHDLModel.VHDLModel import PackageBody as VHDLModel_PackageBody +from pyVHDLModel.VHDLModel import Context as VHDLModel_Context +from pyVHDLModel.VHDLModel import Configuration as VHDLModel_Configuration + +from libghdl.thin.vhdl import nodes, pyutils + +from pyGHDL.dom.Common import GHDLMixin + +__all__ = [] +__api__ = __all__ + +from pyGHDL.dom.InterfaceItem import GenericConstantInterfaceItem, PortSignalInterfaceItem + + +@export +class Entity(VHDLModel_Entity, GHDLMixin): + + @classmethod + def parse(cls, libraryUnit): + name = cls._ghdlNodeToName(libraryUnit) + entity = cls(name) + + cls.__parseGenerics(libraryUnit, entity) + cls.__parsePorts(libraryUnit, entity) + + return entity + + @classmethod + def __ghdlGetGenerics(cls, entity): + return pyutils.chain_iter(nodes.Get_Generic_Chain(entity)) + + @classmethod + def __ghdlGetPorts(cls, entity): + return pyutils.chain_iter(nodes.Get_Port_Chain(entity)) + + @classmethod + def __parseGenerics(cls, libraryUnit, entity): + for generic in cls.__ghdlGetGenerics(libraryUnit): + genericConstant = GenericConstantInterfaceItem.parse(generic) + entity.GenericItems.append(genericConstant) + + @classmethod + def __parsePorts(cls, libraryUnit, entity): + for port in cls.__ghdlGetPorts(libraryUnit): + signalPort = PortSignalInterfaceItem.parse(port) + entity.PortItems.append(signalPort) + +@export +class Architecture(VHDLModel_Architecture, GHDLMixin): + def __init__(self, name: str, entityName: str): + super().__init__(name) + + self.__entityName = entityName + + @classmethod + def parse(cls, libraryUnit): + name = cls._ghdlNodeToName(libraryUnit) + entityName = cls._ghdlNodeToName(nodes.Get_Entity_Name(libraryUnit)) + + return cls(name, entityName) + + def resolve(self): + pass + +@export +class Package(VHDLModel_Package, GHDLMixin): + + @classmethod + def parse(cls, libraryUnit): + name = cls._ghdlNodeToName(libraryUnit) + return cls(name) + +@export +class PackageBody(VHDLModel_PackageBody, GHDLMixin): + + @classmethod + def parse(cls, libraryUnit): + name = cls._ghdlNodeToName(libraryUnit) + return cls(name) + +@export +class Context(VHDLModel_Context, GHDLMixin): + + @classmethod + def parse(cls, libraryUnit): + name = cls._ghdlNodeToName(libraryUnit) + return cls(name) + +@export +class Configuration(VHDLModel_Configuration, GHDLMixin): + + @classmethod + def parse(cls, libraryUnit): + name = cls._ghdlNodeToName(libraryUnit) + return cls(name) diff --git a/pyGHDL/dom/InterfaceItem.py b/pyGHDL/dom/InterfaceItem.py new file mode 100644 index 000000000..0833c2547 --- /dev/null +++ b/pyGHDL/dom/InterfaceItem.py @@ -0,0 +1,33 @@ +from pydecor import export + +from pyVHDLModel.VHDLModel import PortSignalInterfaceItem as VHDLModel_PortSignalInterfaceItem +from pyVHDLModel.VHDLModel import GenericConstantInterfaceItem as VHDLModel_GenericConstantInterfaceItem + +from pyGHDL.dom.Common import GHDLMixin + +__all__ = [] +__api__ = __all__ + + +@export +class GenericConstantInterfaceItem(VHDLModel_GenericConstantInterfaceItem, GHDLMixin): + @classmethod + def parse(cls, generic): + name = cls._ghdlNodeToName(generic) + mode = cls._ghdlPortToMode(generic) + + generic = cls(name, mode) + + return generic + + +@export +class PortSignalInterfaceItem(VHDLModel_PortSignalInterfaceItem, GHDLMixin): + @classmethod + def parse(cls, port): + name = cls._ghdlNodeToName(port) + mode = cls._ghdlPortToMode(port) + + port = cls(name, mode) + + return port diff --git a/pyGHDL/dom/Misc.py b/pyGHDL/dom/Misc.py new file mode 100644 index 000000000..ab47576fc --- /dev/null +++ b/pyGHDL/dom/Misc.py @@ -0,0 +1,96 @@ +from pathlib import Path +from typing import Any + +from pydecor import export + +from pyVHDLModel.VHDLModel import Design as VHDLModel_Design +from pyVHDLModel.VHDLModel import Library as VHDLModel_Library +from pyVHDLModel.VHDLModel import Document as VHDLModel_Document + +import libghdl +from libghdl.thin import name_table, files_map, errorout_console +from libghdl.thin.vhdl import nodes, sem_lib + +from pyGHDL.dom.Common import LibGHDLException, GHDLException +from pyGHDL.dom.DesignUnit import Entity, Architecture, Package, PackageBody, Context, Configuration + +__all__ = [] +__api__ = __all__ + + +@export +class Design(VHDLModel_Design): + def __init__(self): + super().__init__() + + self.__ghdl_init() + + def __ghdl_init(self): + """Initialization: set options and then load libraries""" + + # Print error messages on the console + errorout_console.Install_Handler() + + libghdl.set_option(b"--std=08") + libghdl.analyze_init() + +@export +class Library(VHDLModel_Library): + pass + + +@export +class Document(VHDLModel_Document): + __ghdlFileID: Any + __ghdlSourceFileEntry: Any + __ghdlFile: Any + + def __init__(self, path : Path = None): + super().__init__(path) + + self.__ghdl_init() + + def __ghdl_init(self): + # Read input file + self.__ghdlFileID = name_table.Get_Identifier(str(self.Path).encode("utf_8")) + self.__ghdlSourceFileEntry = files_map.Read_Source_File(name_table.Null_Identifier, self.__ghdlFileID) + if self.__ghdlSourceFileEntry == files_map.No_Source_File_Entry: + raise LibGHDLException("Cannot load file '{!s}'".format(self.Path)) + + # parse + self.__ghdlFile = sem_lib.Load_File(self.__ghdlSourceFileEntry) + + def parse(self): + unit = nodes.Get_First_Design_Unit(self.__ghdlFile) + while unit != nodes.Null_Iir: + libraryUnit = nodes.Get_Library_Unit(unit) + nodeKind = nodes.Get_Kind(libraryUnit) + + if (nodeKind == nodes.Iir_Kind.Entity_Declaration): + entity = Entity.parse(libraryUnit) + self.Entities.append(entity) + + elif (nodeKind == nodes.Iir_Kind.Architecture_Body): + architecture = Architecture.parse(libraryUnit) + self.Architectures.append(architecture) + + elif (nodeKind == nodes.Iir_Kind.Package_Declaration): + package = Package.parse(libraryUnit) + self.Packages.append(package) + + elif (nodeKind == nodes.Iir_Kind.Package_Body): + packageBody = PackageBody.parse(libraryUnit) + self.PackageBodies.append(packageBody) + + elif (nodeKind == nodes.Iir_Kind.Context_Declaration): + context = Context.parse(libraryUnit) + self.Contexts.append(context) + + elif (nodeKind == nodes.Iir_Kind.Configuration_Declaration): + configuration = Configuration.parse(libraryUnit) + self.Configurations.append(configuration) + + else: + raise GHDLException("Unknown design unit kind.") + + unit = nodes.Get_Chain(unit) diff --git a/pyGHDL/dom/__init__.py b/pyGHDL/dom/__init__.py new file mode 100644 index 000000000..df2dfb868 --- /dev/null +++ b/pyGHDL/dom/__init__.py @@ -0,0 +1,4 @@ +from pydecor import export + +__all__ = [] +__api__ = __all__ -- cgit v1.2.3