Source code for pyIPCMI.DataBase.Solution

# EMACS settings: -*-	tab-width: 2; indent-tabs-mode: t; python-indent-offset: 2 -*-
# vim: tabstop=2:shiftwidth=2:noexpandtab
# kate: tab-width 2; replace-tabs off; indent-width 2;
#
# ==============================================================================
# Authors:          Patrick Lehmann
#
# Python Class:     TODO
#
# License:
# ==============================================================================
# Copyright 2017-2018 Patrick Lehmann - Bötzingen, Germany
# Copyright 2007-2016 Technische Universität Dresden - Germany
#                     Chair of VLSI-Design, Diagnostics and Architecture
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ==============================================================================
#
# load dependencies
from collections        import OrderedDict
from textwrap           import dedent

from lib.Decorators     import ILazyLoadable, LazyLoadTrigger
from pyIPCMI.Base.Exceptions    import CommonException
from pyIPCMI.Base.Project       import Project as BaseProject, File, FileTypes, VHDLSourceFile, VerilogSourceFile, CocotbSourceFile  #, ProjectFile
from pyIPCMI.Parser.FilesParser import FilesParserMixIn
from pyIPCMI.Parser.RulesParser import RulesParserMixIn
from pyIPCMI.DataBase           import __pyIPCMI_SOLUTION_KEYWORD__
from pyIPCMI.DataBase.Entity    import Visibility
from pyIPCMI.ToolChain          import ConfigurationException


__api__ = [
	'Base',
	'Repository', 'Solution', 'Project',
	'ISEProject', 'VivadoProject', 'QuartusProject', 'LatticeProject', 'VirtualProject',
	'FileListFile', 'RulesFile'
]
__all__ = __api__


[docs]class Base(ILazyLoadable): """ Base class for Repository, Solution and Project. It implements ILazyLoadable. """ def __init__(self, host, sectionPrefix, sectionID, parent): ILazyLoadable.__init__(self) self._host = host self._id = sectionID self._configSection = "{0}.{1}".format(sectionPrefix, sectionID) self._parent = parent self._Load() @property def ID(self): return self._id @property def Parent(self): return self._parent @property def ConfigSectionName(self): return self._configSection
[docs] def _Load(self): """Implement this method for early loading.""" pass
[docs]class Repository(Base): def __init__(self, host): self._solutions = {} kind = "Public" if host.Config.has_option("INSTALL.PoC", "RepositoryKind"): kind = host.Config[host.LibraryKey]['RepositoryKind'] self._kind = Visibility.Parse(kind) super().__init__(host, "SOLUTION", "Solutions", None) @property def Kind(self): return self._kind
[docs] def _Load(self): self._LazyLoadable_Load()
def __contains__(self, item): return (item.lower() in self._solutions) def __getitem__(self, item): return self._solutions[item.lower()]
[docs] def _LazyLoadable_Load(self): super()._LazyLoadable_Load() # load solutions for slnID in self._host.Config[self._configSection]: if (self._host.Config[self._configSection][slnID] == __pyIPCMI_SOLUTION_KEYWORD__): self._solutions[slnID.lower()] = Solution(self._host, slnID, self)
[docs] def AddSolution(self, solutionID, solutionName, solutionRootPath): solution = Solution(self._host, solutionID, self) solution.Name = solutionName solution.Path = solutionRootPath self._host.Config[self._configSection][solutionID] = __pyIPCMI_SOLUTION_KEYWORD__ self._solutions[solutionID] = solution solution.Register() solution.CreateFiles() return solution
[docs] def RemoveSolution(self, solution): if isinstance(solution, str): solution = self._solutions[solution.lower()] elif (not isinstance(solution, Solution)): raise ValueError("Parameter solution is not of type str or Solution.") solution.Unregister() self._host.Config.remove_option(self._configSection, solution.ID)
@property @LazyLoadTrigger def Solutions(self): """Returns the list of all registered solutions.""" return self._solutions.values() @property @LazyLoadTrigger def SolutionNames(self): """Returns the identifier list of all registered solutions.""" return self._solutions.keys()
[docs]class Solution(Base): __SOLUTION_CONFIG_FILE__ = "solution.config.ini" __SOLUTION_DEFAULT_FILE__ = "solution.defaults.ini" def __init__(self, host, slnID, parent): super().__init__(host, "SOLUTION", slnID, parent) self._name = None self._path = None self._projects = {}
[docs] def Register(self): self._host.Config[self._configSection] = OrderedDict() self._host.Config[self._configSection]['Name'] = self._name self._host.Config[self._configSection]['Path'] = self._path.as_posix()
[docs] def Unregister(self): self._host.Config.remove_section(self._configSection)
[docs] def CreateFiles(self): solutionConfigPath = self._path / ".pyIPCMI" if (not self._path.is_absolute()): solutionConfigPath = self._host.Directories.Root / solutionConfigPath try: solutionConfigPath.mkdir(parents=True) except OSError as ex: raise ConfigurationException("Error while creating '{0!s}'.".format(solutionConfigPath)) from ex solutionConfigFile = solutionConfigPath / self.__SOLUTION_CONFIG_FILE__ with solutionConfigFile.open('w') as fileHandle: fileContent = dedent("""\ [SOLUTION.{slnID}] DefaultLibrary = """.format(slnID=self._id)) fileHandle.write(fileContent) solutionDefaultFile = solutionConfigPath / self.__SOLUTION_DEFAULT_FILE__ with solutionDefaultFile.open('w') as fileHandle: fileContent = dedent("""\ [SOLUTION.DEFAULTS] """) fileHandle.write(fileContent)
[docs] def _LazyLoadable_Load(self): super()._LazyLoadable_Load() self._name = self._host.Config[self._configSection]['Name'] self._path = self._host.Directories.Root / self._host.Config[self._configSection]['Path'] solutionConfigPath = self._path / ".pyIPCMI" if (not self._path.is_absolute()): solutionConfigPath = self._host.Directories.Root / solutionConfigPath configFiles = [ solutionConfigPath / self.__SOLUTION_CONFIG_FILE__, solutionConfigPath / self.__SOLUTION_DEFAULT_FILE__ ] for configFile in configFiles: if (not configFile.exists()): raise ConfigurationException("Solution configuration file '{0!s}' not found.".format(configFile)) from FileNotFoundError(str(configFile)) self._host.Config.read(str(configFile)) # load projects for option in self._host.Config[self._configSection]: project = None if (self._host.Config[self._configSection][option] == "ISEProject"): project = ISEProject(self._host, option, self) elif (self._host.Config[self._configSection][option] == "VivadoProject"): project = VivadoProject(self._host, option, self) elif (self._host.Config[self._configSection][option] == "QuartusProject"): project = QuartusProject(self._host, option, self) elif (self._host.Config[self._configSection][option] == "LatticeProject"): project = LatticeProject(self._host, option, self) if (project is not None): self._projects[option.lower()] = project
@property @LazyLoadTrigger def Name(self): """Gets the name of this solution.""" return self._name @Name.setter def Name(self, value): """Sets the name of this solution.""" self._name = value @property @LazyLoadTrigger def Path(self): """Gets the path to the solution.""" return self._path @Path.setter def Path(self, value): """Sets the path of the solution.""" self._path = value @property @LazyLoadTrigger def Projects(self): """Gets a list of all registered projects.""" return self._projects.values() @property @LazyLoadTrigger def ProjectNames(self): """Gets a list of identifiers of all registered projects.""" return self._projects.keys()
[docs]class Project(Base): def __init__(self, host, prjID, parent): super().__init__(host, "PROJECT", prjID, parent) self._name = None @property @LazyLoadTrigger def Name(self): """Gets the name of this solution.""" return self._name @Name.setter def Name(self, value): """Sets the name of this solution.""" self._name = value
[docs]class ISEProject(Project): pass
[docs]class VivadoProject(Project): pass
[docs]class QuartusProject(Project): pass
[docs]class LatticeProject(Project): pass
[docs]class VirtualProject(BaseProject): pass
[docs]class FileListFile(File, FilesParserMixIn): _FileType = FileTypes.FileListFile def __init__(self, file, project = None, fileSet = None): super().__init__(file, project=project, fileSet=fileSet) FilesParserMixIn.__init__(self) self._variables = None self._classFileListFile = FileListFile self._classVHDLSourceFile = VHDLSourceFile self._classVerilogSourceFile = VerilogSourceFile self._classCocotbSourceFile = CocotbSourceFile
[docs] def Parse(self, host): if (self._fileSet is None): raise CommonException("File '{0!s}' is not associated to a fileset.".format(self._file)) if (self._project is None): raise CommonException("File '{0!s}' is not associated to a project.".format(self._file)) if (self._project.RootDirectory is None): raise CommonException("No RootDirectory configured for this project.") # prepare FilesParserMixIn environment self._rootDirectory = self.Project.RootDirectory self._variables = self.Project.GetVariables() self._Parse() self._Resolve(host)
[docs] def CopyFilesToFileSet(self): for file in self._files: self._fileSet.AddFile(file)
[docs] def CopyExternalLibraries(self): for lib in self._libraries: self._project.AddExternalVHDLLibraries(lib)
def __str__(self): return "FileList file: '{0!s}".format(self._file)
[docs]class RulesFile(File, RulesParserMixIn): _FileType = FileTypes.RulesFile def __init__(self, file, project = None, fileSet = None): super().__init__(file, project=project, fileSet=fileSet) RulesParserMixIn.__init__(self) self._variables = None
[docs] def Parse(self): if (self._fileSet is None): raise CommonException("File '{0!s}' is not associated to a fileset.".format(self._file)) if (self._project is None): raise CommonException("File '{0!s}' is not associated to a project.".format(self._file)) if (self._project.RootDirectory is None): raise CommonException("No RootDirectory configured for this project.") # prepare FilesParserMixIn environment self._rootDirectory = self.Project.RootDirectory self._variables = self.Project.GetVariables() self._Parse() self._Resolve()
def __str__(self): return "FileList file: '{0!s}".format(self._file)