OpenCores
URL https://opencores.org/ocsvn/radiohdl/radiohdl/trunk

Subversion Repositories radiohdl

[/] [radiohdl/] [trunk/] [core/] [hdl_libraries_wizard.py] - Rev 4

Go to most recent revision | Compare with Previous | Blame | View Log

###############################################################################
#
# Copyright (C) 2014
# ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
# P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
#
# 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 3 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 <http://www.gnu.org/licenses/>.
#
###############################################################################
 
"""HDL configuration for building simulation and synthesis targets.
 
   There should be one hdl_buildset_<buildset>.cfg file per buildset somewhere in the
   toolRootDir and at least one hdllib.cfg file somewhere in the libRootDir.
   Every HDL library that is in the libRootDir can be found if it has a hdllib.cfg file.
   Together the hdl_buildset_<buildset>.cfg and hdllib.cfg files contain all the keys and
   values that are sufficient to be able to build the targets for the HDL
   library. The possible targets are:
 
   - compile to created the library binaries for simulation
   - synthesize to created an image that can be loaded ion the FPGA
   - verify VHDL test benches in simulation
   - verify Python test cases via the MM control interface in simulation
   - validate Python test cases on hardware via the MM control interface
 
   The contents of the cfg files consist of a series of key - value pairs
   that are read into a dictionary as defined in hdl_configfile.py. Whether
   the key is a valid key depends on the application that interprets the
   dictionary.
 
   The methods can have the library dictionary or the library name as
   argument. The default arguments are the self.libs.dicts and the
   corresponding self.lib_names. The argument can be a list or a single value.
   Similar the return can be a list or a single value, because a list of one
   element is unlistified.
 
"""
 
import sys
import fnmatch
from os import listdir, walk, getenv
from os.path import expandvars, isabs, join, isfile
import shutil
from distutils.dir_util import copy_tree
from argparse import ArgumentParser
import collections
import common_radiohdl as cm
from configfile import ConfigFile
from hdl_configfile import HdlBuildset
from hdl_configtree import HdlLibTree
 
__all__ = ['HdlLibrariesWizard']
 
 
class HdlLibrariesWizard:
 
    def __init__(self, toolRootDir, toolFileName, libFileName='hdllib.cfg', libFileSections=None):
        """Get tool dictionary info from toolRootDir and all HDL library dictionary info for it
 
           - self.tool.dicts = single dictionary that contains the tool info (only one tool dict in dicts list)
           - self.libs.dicts = list of dictionaries that contains the info of the HDL libraries.
 
           The libRootDir parameter is defined in the hdl_buildset_<buildset>.cfg file and is the root directory from where the hdllib.cfg
           files are searched for.
 
           - self.lib_names = the library names of self.libs.dicts
 
           In parallel to the self.libs.dicts list of dictionaries a list of self.lib_names is created to be able to identify
           a HDL library dict also by its library name. Iherefore it is important that the indexing of parallel lists remains
           intact at all times.
 
           - self.technologyNames = the technologyNames parameter is defined in the hdl_buildset_<buildset>.cfg file. All generic HDL
             libraries and these technology specific libraries are kept. If self.technologyNames is:
             []                              : Keep all HDL libraries that were found.
             ['ip_stratixiv', 'ip_arria10']  : The HDL libraries with a hdl_lib_technology that is not '' or does not match one of the technologies
                                               in technologyNames are removed from the list of HDL library dictionaries.
 
           - self.removed_libs = contains the HDL library dicts that have been removed from self.libs.dicts, because they are for
                                  a technology that is not within technologyNames.
 
           Keep lists of all unavailable library names that were found at the hdl_lib_uses_synth, hdl_lib_uses_ip, hdl_lib_uses_sim and
           hdl_lib_include_ip keys in the self.libs.dicts:
 
           - self.unavailable_use_libs = self.unavailable_use_synth_libs + self.unavailable_use_ip_libs + self.unavailable_use_sim_libs
           - self.unavailable_include_ip_libs
 
           Unavailable used libraries can be missing for a valid reason when they are not required (e.g. IP for another technology). Being able to
           ignore missing libraries does require that the entities from these libraries are instantiated as components in the VHDL. The difference
           between a removed library and an unavailable library is that for a removed library the HDL config information is still known, whereas
           for an unavailable library it is not. Therefore the library clause names for referred but unavailable HDL libraries are disclosed at the
           'hdl_lib_disclose_library_clause_names' keys of the libraries that use them and kept in a dictionary:
 
           - self.disclosed_library_clause_names
 
        """
        print("HdlLibrariesWizard(toolRootDir=%s, toolFileName=%s, libFileName=%s, libFileSections=%s)"
              % (toolRootDir, toolFileName, libFileName, libFileSections))
        self.toolRootDir = toolRootDir  # TODO almost obsolete
 
        # read the buildset file. This file contains major information about paths, technologies, and so on
        full_buildsetfile_name = "%s/%s" % (toolRootDir, toolFileName)
        buildset_info = HdlBuildset(full_buildsetfile_name)
        buildset_info.resolve_key_references()
        self.buildset = buildset_info.content
 
        # HDL library config files
        self.libRootDirs = [expandvars(rootdir) for rootdir in self.buildset['lib_root_dirs'].replace("\t", " ").split(" ")
                            if rootdir != '']
        self.libs = HdlLibTree(rootdirs=self.libRootDirs,
                               filename=libFileName,
                               sections=libFileSections)   # library dict files
        if len(self.libs.configfiles) == 0:
            sys.exit('Error : No HDL library config files found')
        print("Found %d hdllib files:" % len(self.libs.configfiles))
 
        # Substitute key words occurring in hdllib.cfg files with their value.
        self.substitute_key_words()
 
        self.familyNames = self.buildset['family_names'].split()
        print("### self.familyNames = ", self.familyNames)
 
        # Keep the generic HDL libraries and remove those that do not match the specified IP technologies
        self.technologyNames = self.buildset['technology_names'].split()
        print("### self.technologyNames = ", self.technologyNames)
        self.removed_libs = {}
 
        buildset_files = []
        for root, dirs, files in walk(join(getenv("RADIOHDL_GEAR"), 'config')):
            for name in files:
                if fnmatch.fnmatch(name, 'hdl_buildset_*.cfg'):
                    buildset_files.append(join(root, name))
        all_buildset_names = [bs[bs.rfind('_')+1:bs.rfind('.')] for bs in buildset_files]
        # print(all_buildset_names)
 
        for cfglib_name in list(self.libs.configfiles.keys()):
            techname = self.libs.configfiles[cfglib_name]['hdl_lib_technology']
            if (techname != '' and techname not in self.technologyNames):
                # keep the removed libs we need the content of those libs later.
                self.removed_libs[cfglib_name] = self.libs.configfiles[cfglib_name]
            else:
                # accept only projects for active buildset_name
                # this method asume the hdl_lib_name is starting with the buildset_name and ending with 
                # the project name seperated by a '_'
                # for example unb2b_<project_name>
                for buildset_name in sorted(all_buildset_names)[::-1]:
                    if buildset_name == self.buildset['buildset_name']:
                        continue
                    if buildset_name+'_' in self.libs.configfiles[cfglib_name]['hdl_lib_name']:
                        # keep the removed libs we need the content of those libs later.
                        self.removed_libs[cfglib_name] = self.libs.configfiles[cfglib_name]
 
        self.libs.remove_files_from_tree(list(self.removed_libs.keys()))
        print(len(self.removed_libs), "REMOVED LIBS:", sorted(self.removed_libs))
 
        # Keep list of used HDL library names
        self.lib_names = list(self.libs.configfiles.keys())
        print(len(self.lib_names), "KEPT LIBS:", sorted(self.lib_names))
 
        # No need to check for duplicates since HdlLibTree did that already.
 
        # create dictionary of library names with library clause names that are disclosed at the 'hdl_lib_disclose_library_clause_names' keys.
        self.disclosed_library_clause_names = {}
        for lib in list(self.libs.configfiles.values()):
            if lib.get_value('hdl_lib_disclose_library_clause_names'):
                key_values = lib.get_value('hdl_lib_disclose_library_clause_names').split()
                lib_name = key_values[0::2]
                lib_clause_name = key_values[1::2]
                lib_pairs = list(zip(lib_name, lib_clause_name))
                # No need to check for duplicate lib_names, because a dictionary cannot have duplicate keys
                for lp in lib_pairs:
                    self.disclosed_library_clause_names[lp[0]] = lp[1]
        # Check whether the used libraries from the self.libs.dicts keys indeed exist, otherwise remove them from the dictionary key
        # string and add the used library name to the list of unavailable used library names and check that the library use clause
        # name was disclosed at the 'hdl_lib_disclose_library_clause_names' key. In this way other methods do not have to check a
        # used library does indeed exist.
        self.unavailable_use_synth_libs = []
        self.unavailable_use_ip_libs = []
        self.unavailable_use_sim_libs = []
        self.unavailable_include_ip_libs = []
        for lib in list(self.libs.configfiles.values()):
            use_synth_libs = []
            use_ip_libs = []
            use_sim_libs = []
            include_ip_libs = []
            if lib.get_value('hdl_lib_uses_synth'):
                use_synth_libs = lib.get_value('hdl_lib_uses_synth').split()
            if lib.get_value('hdl_lib_uses_ip'):
                use_ip_libs += lib.get_value('hdl_lib_uses_ip').split()
            if lib.get_value('hdl_lib_uses_sim'):
                use_sim_libs += lib.get_value('hdl_lib_uses_sim').split()
            if lib.get_value('hdl_lib_include_ip'):
                include_ip_libs = lib.get_value('hdl_lib_include_ip').split()
            for use_name in use_synth_libs:
                if (use_name not in self.lib_names) and (use_name not in self.removed_libs):
                    lib['hdl_lib_uses_synth'] = cm.remove_from_list_string(lib['hdl_lib_uses_synth'], use_name)
                    self.unavailable_use_synth_libs.append(use_name)
                    if use_name not in list(self.disclosed_library_clause_names.keys()):
                        sys.exit("Error : Unavailable library %s at 'hdl_lib_uses_synth' key is not disclosed at 'hdl_lib_disclose_library_clause_names' key in library %s" % (use_name, lib_name))
            for use_name in use_ip_libs:
                if (use_name not in self.lib_names) and (use_name not in self.removed_libs):
                    lib['hdl_lib_uses_ip'] = cm.remove_from_list_string(lib['hdl_lib_uses_ip'], use_name)
                    self.unavailable_use_ip_libs.append(use_name)
                    if use_name not in list(self.disclosed_library_clause_names.keys()):
                        sys.exit("Error : Unavailable library %s at 'hdl_lib_uses_ip' key is not disclosed at 'hdl_lib_disclose_library_clause_names' key in library %s" % (use_name, lib_name))
            for use_name in use_sim_libs:
                if (use_name not in self.lib_names) and (use_name not in self.removed_libs):
                    lib['hdl_lib_uses_sim'] = cm.remove_from_list_string(lib['hdl_lib_uses_sim'], use_name)
                    self.unavailable_use_sim_libs.append(use_name)
                    if use_name not in list(self.disclosed_library_clause_names.keys()):
                        sys.exit("Error : Unavailable library %s at 'hdl_lib_uses_sim' key is not disclosed at 'hdl_lib_disclose_library_clause_names' key in library %s" % (use_name, lib_name))
            for use_name in include_ip_libs:
                if (use_name not in self.lib_names) and (use_name not in self.removed_libs):
                    lib['hdl_lib_include_ip'] = cm.remove_from_list_string(lib['hdl_lib_include_ip'], use_name)
                    self.unavailable_include_ip_libs.append(use_name)
                    if use_name not in list(self.disclosed_library_clause_names.keys()):
                        sys.exit("Error : Unavailable library %s at 'hdl_lib_include_ip' key in library %s is not disclosed at any 'hdl_lib_disclose_library_clause_names' key" % (use_name, lib_name))
        # remove all duplicates from the list
        self.unavailable_use_synth_libs  = cm.unique(self.unavailable_use_synth_libs)
        self.unavailable_use_ip_libs     = cm.unique(self.unavailable_use_ip_libs)
        self.unavailable_use_sim_libs    = cm.unique(self.unavailable_use_sim_libs)
        self.unavailable_include_ip_libs = cm.unique(self.unavailable_include_ip_libs)   # list of include_ip_use_libs
        self.unavailable_use_libs        = self.unavailable_use_synth_libs + self.unavailable_use_ip_libs + self.unavailable_use_sim_libs
        self.unavailable_use_libs        = cm.unique(self.unavailable_use_libs)          # aggregate list of use_*_libs
 
    # The Key value pairs defined in hdltool<buildset>.cfg can be used in hdllib.cfg files. See hdllib.cfg of technology library
    def substitute_key_words(self):
        for lib in list(self.libs.configfiles.values()):
            for lib_key, lib_value in list(lib.content.items()):
                for tool_key, tool_value in list(self.buildset.items()):
                    tool_key_string = '<%s>' % tool_key
                    if tool_key_string in lib_value:
                        lib[lib_key] = lib_value.replace(tool_key_string, tool_value)
 
    def check_library_names(self, check_lib_names, lib_names=None):
        """Check that HDL library names exists within the list of library names, if not then exit with Error message.
           The list of library names can be specified via the argument lib_names, or it defaults to the list of
           self.lib_names of HDL libraries that were found in the toolRootDir for the libFileName of this object.
        """
        if lib_names is None:
            lib_names = self.lib_names
        for check_lib_name in cm.listify(check_lib_names):
            if check_lib_name not in cm.listify(lib_names):
                sys.exit('Error : Unknown HDL library name %s found with %s' % (check_lib_name, cm.method_name()))
 
    def get_used_libs(self, build_type, lib_dict, arg_include_ip_libs=[]):
        """Get the list of used HDL libraries from the lib_dict that this library directly depends on, so only at this HDL library hierachy level.
 
           Which libraries are actually used depends on the build_type. The build_type can be:
            ''      uses all libraries from 'hdl_lib_uses_synth', 'hdl_lib_uses_ip' and 'hdl_lib_uses_sim' in the lib_dict
            'sim'   uses all libraries from 'hdl_lib_uses_synth', 'hdl_lib_uses_ip' and 'hdl_lib_uses_sim' in the lib_dict
            'synth' uses all libraries from 'hdl_lib_uses_synth' in the lib_dict and from 'hdl_lib_uses_ip' it only uses the IP
                    libraries that are mentioned in the local 'hdl_lib_include_ip' key or in the global arg_include_ip_libs
 
           The 'hdl_lib_uses_*' keys all appear locally in the same hdllib.cfg file. The 'hdl_lib_include_ip' key appears at this level or at
           a higher level (design) library hdllib.cfg file to select which of all available 'hdl_lib_uses_ip' IP libraries will actually be
           used in the design. The 'hdl_lib_include_ip' cannot appear in a lower level hdllib.cfg, because a lower level HDL library cannot
           depend on a higher level HDL library. Therefore the IP libraries that need to be included from 'hdl_lib_uses_ip' will be known in
           include_ip_libs.
        """
        # Get local library dependencies
        use_synth_libs = []
        use_ip_libs = []
        use_sim_libs = []
        include_ip_libs = []
        if 'hdl_lib_uses_synth' in lib_dict.content:
            use_synth_libs = lib_dict['hdl_lib_uses_synth'].split()
        if 'hdl_lib_uses_ip' in lib_dict.content:
            use_ip_libs += lib_dict['hdl_lib_uses_ip'].split()
        if 'hdl_lib_uses_sim' in lib_dict.content:
            use_sim_libs += lib_dict['hdl_lib_uses_sim'].split()
        if 'hdl_lib_include_ip' in lib_dict.content:
            include_ip_libs = lib_dict['hdl_lib_include_ip'].split()
 
        # Append include_ip_libs from this level to the global list of arg_include_ip_libs
        include_ip_libs = list(arg_include_ip_libs) + include_ip_libs
 
        # Get the actually use_libs for lib_dict
        use_libs = use_synth_libs + use_ip_libs + use_sim_libs  # default include all IP, so ignore include_ip_libs
        if build_type == 'sim':
            use_libs = use_synth_libs + use_ip_libs + use_sim_libs    # for simulation included all IP, so ignore include_ip_libs
        if build_type == 'synth':
            use_libs = use_synth_libs
            # For synthesis only keep the local use_ip_libs if it is mentioned in the global include_ip_libs. Vice versa also only
            # include the global include_ip_libs if they appear in a local use_ip_libs, to avoid that an IP library that is mentioned
            # in the global include_ip_libs gets included while it is not instantiated anywhere in the design.
            for ip_lib in use_ip_libs:
                if ip_lib in include_ip_libs:
                    use_libs += [ip_lib]
 
        # Remove any duplicate library names from the lists
        use_libs = cm.unique(use_libs)
        include_ip_libs = cm.unique(include_ip_libs)
 
        # Remove libraries that are in the removed technologies (use list() to take copy)
        for use_name in list(use_libs):
            if use_name in self.removed_libs:
                use_libs.remove(use_name)
        for use_name in list(include_ip_libs):
            if use_name in self.removed_libs:
                include_ip_libs.remove(use_name)
 
        return use_libs, include_ip_libs
 
    def derive_all_use_libs(self, build_type, lib_name, arg_include_ip_libs=[]):
        """Recursively derive a complete list of all HDL libraries that the specified HDL lib_name library depends on, so from this
           HDL library down the entire hierachy.
 
           The hdl_lib_uses_* key only needs to contain all libraries that are declared at the VHDL LIBRARY clauses of the
           source files in this VHDL library. This derive_all_use_libs() will recursively find all deeper level VHDL libraries as well.
 
           The arg_include_ip_libs selects the IP library to keep from 'hdl_lib_uses_ip'. The include_ip_libs is passed on
           through the recursion hierarchy via arg_include_ip_libs to ensure that the from the top level library down all
           multiple choice IP libraries in 'hdl_lib_uses_ip' that need to be included are indeed included. The multiple choice IP
           libraries in 'hdl_lib_uses_ip' that are not in include_ip_libs are excluded.
 
           Note:
           . Only the generic HDL libraries and the technology specific libraries that match self.technologyNames are used,
             because the other technology libraries have been removed from self.libs.dicts already at __init__() and from the
             library dependency lists in get_used_libs()
           . If Python breaks because recursion limit is reached, then two hdllib.cfg probably mutually use eachother which is
             not allowed.
        """
        # use list() to take local copy, to avoid next that default empty list argument arg_include_ip_libs=[] gets disturbed
        include_ip_libs = list(arg_include_ip_libs)
        if lib_name in self.lib_names:
            all_use_libs = [lib_name]
            lib_dict = self.libs.configfiles[lib_name]
            use_libs, include_ip_libs = self.get_used_libs(build_type, lib_dict, include_ip_libs)
 
            for use_lib in use_libs:
                if use_lib not in all_use_libs:
                    all_use_libs.append(use_lib)
                    # use recursion to include all used libs
                    all_use_libs += self.derive_all_use_libs(build_type, use_lib, include_ip_libs)
            # remove all duplicates from the list
            return cm.unique(all_use_libs)
        else:
            sys.exit('Error : Unknown HDL library name %s in %s()' % (lib_name, cm.method_name()))
 
    def derive_lib_order(self, build_type, lib_name, lib_names=None):
        """Derive the dependency order for all HDL libraries in lib_names that HDL library lib_name depends on.
        """
        if lib_names is None:
            # At first entry derive the list of all HDL libraries that lib_name depends on
            lib_names = self.derive_all_use_libs(build_type, lib_name)
 
        # Derive the order of all HDL libraries that lib_name depends on, start with the order of lib_names
        lib_dicts = self.libs.get_configfiles('hdl_lib_name', values=lib_names)
        # use list() to take local copy to avoid modifying list order of self.lib_names which matches self.libs.dicts list order
        lib_order = list(lib_names)
        for lib_dict in lib_dicts:
            lib_name = lib_dict['hdl_lib_name']
            use_libs, _ = self.get_used_libs('', lib_dict, [])
            for use_lib in use_libs:
                if use_lib in lib_names:
                    if lib_order.index(use_lib) > lib_order.index(lib_name):
                        lib_order.remove(use_lib)
                        lib_order.insert(lib_order.index(lib_name), use_lib)  # move used lib to just before this lib
        # use recursion to keep on reordering the lib_order until it is stable
        if lib_names != lib_order:
            lib_order = self.derive_lib_order(build_type, lib_name, lib_order)
        return lib_order
 
    def get_lib_dicts_from_lib_names(self, lib_names=None):
        """Get list the HDL libraries lib_dicts from list of HDL libraries lib_names and preseve the library order.
        """
        if lib_names is None:
            lib_names = self.lib_names
 
        # Cannot use:
        # lib_dicts = self.libs.get_configfiles('hdl_lib_name', values=lib_names)
        # because then the order of self.libs.dicts is used
        lib_dicts = []
        for lib_name in cm.listify(lib_names):
            lib_dicts.append(self.libs.configfiles[lib_name])
        return lib_dicts
 
    def get_lib_names_from_lib_dicts(self, lib_dicts=None):
        """Get list the HDL libraries lib_names from list of HDL libraries lib_dicts and preseve the library order.
        """
        lib_names = self.libs.get_key_values('hdl_lib_name', lib_dicts)
        return lib_names
 
    def get_tool_build_dir(self, build_type):
        """Get the central tool build directory.
 
        The build_type can be:
            'sim'   uses the 'sim_tool_name'   key in the self.buildset
            'synth' uses the 'synth_tool_name' key in the self.buildset
            When another name is used that name is used directly as toolname in the construction of the path.
 
        The function returns a tuple with the following four components:
            - the absolute path to the central main build directory
            - the buildset_name key value as subdirectory
            - the toolname as subdirectory (derived from *_tool_name or the given value of 'build_type')
            - project_deeper_subdir. See explanation below.
 
        The project file will be located in the build dir or at some levels deeper in the build dir.
        These optional extra subdirectory levels allow for relative file reference from project file
        location. This is useful to be able to keep memory initialisation files in the library build
        directory that are referred to using some fixed ../../ path in the HDL code.
            - project_deeper_subdir = '' when project_dir_depth_<build_type> = 0 or not in buildset
            - project_deeper_subdir = 'p/' when project_dir_depth_<build_type> = 1
            - project_deeper_subdir = 'p/p/' when project_dir_depth_<build_type> = 2,
            - project_deeper_subdir = 'p/p/p/' when project_dir_depth_<build_type> = 3, etc
        """
        # Determine build_maindir
        build_maindir = expandvars('${RADIOHDL_BUILD_DIR}')
        if not isabs(build_maindir):
            sys.exit('Error : The build_dir value must be an absolute path')
 
        # Determine build_buildset_dir
        build_buildset_dir = self.buildset['buildset_name']
 
        # Determine build_tooldir
        tool_name_key = build_type + '_tool_name'
        if tool_name_key in self.buildset:
            build_tooldir = self.buildset[tool_name_key]
        else:
            build_tooldir = build_type
 
        # Determine project_deeper_subdir
        project_dir_depth_key = 'project_dir_depth_' + build_type
        if project_dir_depth_key not in self.buildset:
            project_deeper_subdir = ''
        else:
            project_deeper_subdir = 'p/' * int(self.buildset[project_dir_depth_key])
 
        return build_maindir, build_buildset_dir, build_tooldir, project_deeper_subdir
 
    def get_lib_build_dirs(self, build_type, lib_dicts=None):
        """Get the subdirectories within the central tool build directory for all HDL libraries in the specified list of lib_dicts.
 
        The build_type can be:
            'sim'   uses the 'sim_tool_name'   key in the self.buildset
            'synth' uses the 'synth_tool_name' key in the self.buildset
 
        The build dir key value must be an absolute directory path. The lib build dir consists of
            - the absolute path to the central main build directory
            - the buildset_name key value as subdirectory
            - the tool_name_key value as subdirectory
            - the library name as library subdirectory
            - zero or more extra subdirectory levels to allow for relative file reference from project file location
        """
        if lib_dicts is None:
            lib_dicts = list(self.libs.configfiles.values())
        build_maindir, build_buildset_dir, build_tooldir, project_deeper_subdir = self.get_tool_build_dir(build_type)
        build_dirs = []
        for lib_dict in cm.listify(lib_dicts):
            lib_name = lib_dict['hdl_lib_name']
            build_dirs.append(join(build_maindir, build_buildset_dir, build_tooldir, lib_name, project_deeper_subdir))  # central build main directory with subdirectory per library
        return cm.unlistify(build_dirs)
 
    def create_lib_order_files(self, build_type, lib_names=None):
        """Create the compile order file '<lib_name>_lib_order.txt' for all HDL libraries in the specified list of lib_names.
 
           The file is stored in the sim build directory of the HDL library.
           The file is read by commands.do in Modelsim to avoid having to derive the library compile order in TCL.
        """
        if lib_names is None:
            lib_names = self.lib_names
 
        lib_dicts = self.libs.get_configfiles(key='hdl_lib_name', values=lib_names)
        for lib_dict in lib_dicts:
            lib_name = lib_dict['hdl_lib_name']
            lib_order = self.derive_lib_order(build_type, lib_name)
            file_name = lib_name + '_lib_order.txt'
            file_path = self.get_lib_build_dirs('sim', lib_dicts=lib_dict)
            cm.mkdir(file_path)
            filePathName = join(file_path, file_name)
            with open(filePathName, 'w') as fp:
                for lib in lib_order:
                    fp.write('%s ' % lib)
        print("Created {} lib-order files".format(len(lib_dicts)))
 
    # Methods to create sub directories at various levels in the build directory as defined in HDL tool config file
    def create_sub_directory_in_build_main_dir(self, build_type, subdir_name):
        """Create <subdir_name>/ in the central <build_main>/ directory
        """
        build_maindir, build_buildset_dir, build_tooldir, project_deeper_subdir = self.get_tool_build_dir(build_type)
        subdir_path = join(build_maindir, subdir_name)
        cm.mkdir(subdir_path)
 
    def create_sub_directory_in_build_buildset_dir(self, build_type, subdir_name):
        """Create <subdir_name>/ in the central <build_main>/<build_buildset_dir>/ directory.
        """
        build_maindir, build_buildset_dir, build_tooldir, project_deeper_subdir = self.get_tool_build_dir(build_type)
        subdir_path = join(build_maindir, build_buildset_dir, subdir_name)
        cm.mkdir(subdir_path)
 
    def create_sub_directory_in_build_tool_dir(self, build_type, subdir_name):
        """Create <subdir_name>/ in the central <build_main>/<build_buildset_dir>/<build_tooldir>/ directory.
        """
        build_maindir, build_buildset_dir, build_tooldir, project_deeper_subdir = self.get_tool_build_dir(build_type)
        subdir_path = join(build_maindir, build_buildset_dir, build_tooldir, subdir_name)
        cm.mkdir(subdir_path)
 
    def create_sub_directory_in_build_lib_dir(self, build_type, subdir_name, lib_names=None):
        """Create <subdir_name>/ in project local build directory <lib_name>/ for all HDL libraries in the specified list of lib_names.
        """
        if lib_names is None:
            lib_names = self.lib_names
        lib_dicts = self.libs.get_configfiles('hdl_lib_name', values=lib_names)
        for lib_dict in lib_dicts:
            lib_path = self.get_lib_build_dirs('sim', lib_dicts=lib_dict)
            subdir_path = join(lib_path, subdir_name)
            cm.mkdir(subdir_path)
        print("Created {} subdirectories".format(len(lib_dicts)))
 
    def copy_files(self, build_type, lib_names=None):
        """
        Copy all source directories and source files listed at the <tool_name>_copy_files key.
        The build_type selects the <tool_name>_copy_files key using the <build_type>_tool_name key value
        from the hdl_buildset_<buildset>.cfg.
        The <tool_name>_copy_files key expects a source and a destination pair per listed directory or file:
        - The sources need to be specified with absolute path or relative to the HDL library source directory
          where the hdllib.cfg is stored
        - The destinations need to be specified with absolute path or relative to HDL library build directory
          where the project file (e.g. mpf, qpf) gets stored
 
        Arguments:
        - lib_names  : zero or more HDL libraries
        """
        if lib_names is None:
            lib_names = self.lib_names
 
        lib_dicts          = self.libs.get_configfiles(key='hdl_lib_name', values=lib_names)
        tool_name_key      = build_type + '_tool_name'
        tool_name_value    = self.buildset[tool_name_key]
        tool_name_copy_key = tool_name_value + '_copy_files'
        lib_count          = 0
        dir_count          = 0
        file_count         = 0
        for lib_dict in lib_dicts:
            if tool_name_copy_key in lib_dict.content:
                lib_count += 1
                lib_path       = lib_dict.location
                build_dir_path = self.get_lib_build_dirs(build_type, lib_dicts=lib_dict)
                cm.mkdir(build_dir_path)
                key_values     = lib_dict[tool_name_copy_key].split()
                sources        = key_values[0::2]
                destinations   = key_values[1::2]
                file_io = list(zip(sources, destinations))
                for fpn_io in file_io:
                    sourcePathName  = cm.expand_file_path_name(fpn_io[0], lib_path)
                    destinationPath = cm.expand_file_path_name(fpn_io[1], build_dir_path)
                    # print("Copy '{}'' to '{}'".format(sourcePathName, destinationPath))
                    if isfile(sourcePathName):
                        file_count += 1
                        shutil.copy(sourcePathName, destinationPath)     # copy file
                    else:
                        dir_count += 1
                        copy_tree(sourcePathName, destinationPath)       # copy directory tree (will create new destinationPath directory)
        print("Copied {} files and {} directories for {} libraries".format(file_count, dir_count, lib_count))
 
 
if __name__ == '__main__':
    # Parse command line arguments
    buildsetSelect = sorted([cfgfile[13:-4] for cfgfile in listdir(expandvars('$RADIOHDL_CONFIG'))
                             if cfgfile.startswith("hdl_buildset_") and cfgfile.endswith(".cfg")])
    argparser = ArgumentParser(description='Hdl_config shows several selections of all of your hdllib.cfg files.')
    argparser.add_argument('buildset', help='choose buildset %s' % (buildsetSelect))
    argparser.add_argument('--toplib', default=None, required=False, help='top library to show more information about.')
    args = argparser.parse_args()
 
    # check arguments
    if args.buildset not in buildsetSelect:
        print('buildset %s is not supported' % args.buildset)
        print("Supported buildset are:", buildsetSelect)
        sys.exit(1)
    args.buildsetFile = 'hdl_buildset_' + args.buildset + '.cfg'
 
    # Read the dictionary info from all HDL tool and library configuration files in the current directory and the sub directories
    hdl = HdlLibrariesWizard(toolRootDir=expandvars('${RADIOHDL_CONFIG}'),
                             toolFileName=args.buildsetFile,
                             libFileName='hdllib.cfg')
 
    print('#')
    print('# HdlLibrariesWizard:')
    print('#')
    for libname in list(hdl.libs.configfiles.keys()):
        print("\n", libname)
        libinfo = hdl.libs.configfiles[libname]
        for k, v in libinfo.content.items():
            print(k, '=', v)
    print('')
 
    print('')
    print('Library paths :')
    for libname in list(hdl.libs.configfiles.keys()):
        print('    ', hdl.libs.configfiles[libname].location)
 
    print('')
    print('Library file names :"')
    for libname in list(hdl.libs.configfiles.keys()):
        print('    ', libname)
 
    print('')
    print('Library section headers :')
    for libname, libinfo in hdl.libs.configfiles.items():
        print('    %-52s : %s' % (libname, libinfo['section_headers']))
 
    print('')
    print('Build directories for simulation:')
    for build_dir in hdl.get_lib_build_dirs('sim'):
        print('    ', build_dir)
 
    print('')
    print('Build directories for synthesis:')
    for build_dir in hdl.get_lib_build_dirs('synth'):
        print('    ', build_dir)
 
    print('')
    print('Removed library names = \n', list(hdl.removed_libs.keys()))
 
    print('')
    print("Unavailable library names in any 'hdl_lib_uses_synth' key = \n", hdl.unavailable_use_synth_libs)
    print("Unavailable library names in any 'hdl_lib_uses_ip' key = \n", hdl.unavailable_use_ip_libs)
    print("Unavailable library names in any 'hdl_lib_uses_sim' key = \n", hdl.unavailable_use_sim_libs)
    print("Unavailable library names in any 'hdl_lib_uses_*' key = \n", hdl.unavailable_use_libs)
    print('')
    print("Unavailable library names in any 'hdl_lib_include_ip' key = \n", hdl.unavailable_include_ip_libs)
 
    print('')
    print("Used library clause names that are explicitly disclosed at the 'hdl_lib_disclose_library_clause_names' keys:")
    for key in list(hdl.disclosed_library_clause_names.keys()):
        print('    %-52s : %s' % (key, hdl.disclosed_library_clause_names[key]))
 
    if args.toplib:
        for build_type in ['sim', 'synth']:
            print('')
            print('derive_all_use_libs for %s of %s = \n'
                  % (build_type, args.toplib), hdl.derive_all_use_libs(build_type, args.toplib))
            print('')
            print('derive_lib_order for %s of %s = \n'
                  % (build_type, args.toplib), hdl.derive_lib_order(build_type, args.toplib))
 
 
 

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.