Skip to content
Snippets Groups Projects
Select Git revision
  • d58227b9ab0c81d6c19d4108df2887ca8c21d35d
  • master default
  • update-cudawrappers
  • migrate-cmake
4 results

PosixTime.h

Blame
  • Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    hdl_config.py 21.04 KiB
    ###############################################################################
    #
    # 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 hdltool.cfg file 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 hdltool.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 common_dict_file.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 common as cm
    import common_dict_file
    import sys
    import os
    import os.path
    import shutil
    
    class HdlConfig:
    
        def __init__(self, toolRootDir, libFileName='hdllib.cfg', toolFileName='hdltool.cfg', technologyNames=[]):
            """Get tool dictionary info from toolRootDir and all HDL library dictionary info for it
            
               - self.tool.dicts = single dictionary that contains the tool info
               - self.libs.dicts = list of dictionaries that contains the info of the HDL libraries.
               
               The technologyNames parameter allow control over which HDL libraries are kept. If 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.toolRootDir = toolRootDir
            
            # HDL tool config file
            self.tool = common_dict_file.CommonDictFile(toolRootDir, toolFileName)      # tool dict file
            if self.tool.nof_dicts==0: sys.exit('Error : No HDL tool config file found')
            if self.tool.nof_dicts >1: sys.exit('Error : Multiple HDL tool config files found')
              
            # HDL library config files
            self.libRootDir = os.path.expandvars(self.tool.get_key_values('lib_root_dir'))
            self.libs = common_dict_file.CommonDictFile(self.libRootDir, libFileName)   # library dict files
            if self.libs.nof_dicts==0: sys.exit('Error : No HDL library config file found')
            
            # Keep the generic HDL libraries and remove those that do not match the specified IP technologies
            self.technologyNames = cm.listify(technologyNames)
            self.removed_dicts = []
            if len(self.technologyNames)>0:
                for d in self.libs.dicts:
                    if not(d['hdl_lib_technology']=='' or d['hdl_lib_technology'] in self.technologyNames):
                        self.removed_dicts.append(d)
                for d in self.removed_dicts:
                    self.libs.remove_dict_from_list(d)
                    
            # Keep list of HDL library names
            self.lib_names = self.libs.get_key_values('hdl_lib_name')
            
            # Check that there are no duplicate library names (eg. due to copying a hdlib.cfg without modifying the hdl_lib_name value)
            duplicate_lib_names = cm.list_duplicates(self.lib_names)
            if len(duplicate_lib_names)>0: sys.exit('Error : Duplicate HDL library config file found %s' % duplicate_lib_names)
    
        def get_used_libs(self, build_type, lib_dict, arg_exclude_libs=[]):
            """Get the list of used HDL libraries from the lib_dict and remove the excluded libs.
               - 'hdl_lib_uses_synth' and 'hdl_lib_uses_sim' define the used libraries that are directly used in this library
               - 'hdl_lib_excludes' defines the libraries that must be excluded
            """
            # use list() to take local copy, to avoid next that default empty list argument arg_exclude_libs=[] gets disturbed
            exclude_libs = list(arg_exclude_libs)
            if 'hdl_lib_uses_synth' in lib_dict:
                use_libs = lib_dict['hdl_lib_uses_synth'].split()
            if build_type=='sim':
                if 'hdl_lib_uses_sim' in lib_dict:
                    use_libs += lib_dict['hdl_lib_uses_sim'].split()
            if 'hdl_lib_excludes' in lib_dict:
                exclude_libs += lib_dict['hdl_lib_excludes'].split()
            for exclude_lib in exclude_libs:
                if exclude_lib in use_libs:
                    use_libs.remove(exclude_lib)
            return use_libs, exclude_libs
          
        def derive_all_use_libs(self, build_type, lib_name, arg_exclude_libs=[]):
            """Derive a list of all HDL libraries that the specified HDL lib_name library depends on.
            
               The build_type can be:
                'sim'   uses both the 'hdl_lib_uses_synth' and the 'hdl_lib_uses_sim' key in the lib_dict,
                'synth' uses only the 'hdl_lib_uses_synth' key in the lib_dict
                
               Note:
               . Only the generic HDL libraries and the technology specific libraries that match self.technologyNames are used.
               . The hdl_lib_uses_<build type> key only needs to contain all libraries that are declared at the VHDL LIBRARY
                 clauses of the source files in this library. This derive_all_use_libs() will recursively find all deeper
                 level libraries as well.
               . Pass on exclude_libs through the recursion hierarchy to ensure that the excluded library and all libraries
                 that are used by it and not by any other library are excluded as well.
            """
            # use list() to take local copy, to avoid next that default empty list argument arg_exclude_libs=[] gets disturbed
            exclude_libs = list(arg_exclude_libs)
            if lib_name in self.lib_names:
                all_use_libs = [lib_name]
                lib_dict = self.libs.dicts[self.lib_names.index(lib_name)]
                # use recursion to include all used libs
                use_libs, exclude_libs = self.get_used_libs(build_type, lib_dict, exclude_libs)
                try:
                    use_libs
                    for use_lib in use_libs:
                        if use_lib in self.lib_names:
                            all_use_libs.append(use_lib)
                            all_use_libs += self.derive_all_use_libs(build_type, use_lib, exclude_libs)
                except NameError:
                    pass
                # remove all duplicates from the list
                return cm.unique(all_use_libs)
            else:
                sys.exit('Error : Unknown HDL library name')
    
        def derive_lib_order(self, build_type, lib_names=None):
            """Derive the dependency order for all HDL libraries in the fully specified list of lib_names.
               
               Note:
               . Only the generic HDL libraries and the technology specific libraries that match self.technologyNames are used.
               . The lib_names list must include all used libs, so if necessary first call derive_all_use_libs().
            """
            if lib_names==None: lib_names=self.lib_names
            lib_dicts = self.libs.get_dicts('hdl_lib_name', 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 cm.listify(lib_dicts):
                lib_name = lib_dict['hdl_lib_name']
                use_libs, exclude_libs = self.get_used_libs(build_type, lib_dict, [])
                try:
                    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
                except NameError:
                    pass
            # 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_order)
            return lib_order
                
    
        def get_tool_build_dir(self, build_type):
            """Get the central tool build directory.
            
            The build_type can be:
                'sim'   uses the 'build_dir_sim'   key in the self.tool dictionary
                'synth' uses the 'build_dir_synth' key in the self.tool dictionary
                
            The build dir key value must be an absolute directory path. The tool build dir consists of
                - the absolute path to the central main build directory
                - the tool_name_key value as subdirectory
            """
            build_dir_key = 'build_dir_' + build_type
            tool_name_key = 'tool_name_' + build_type
            if self.tool.get_key_values(build_dir_key)==None:
                sys.exit('Error : Unknown build type for build_dir_key')
            build_maindir = os.path.expandvars(self.tool.get_key_values(build_dir_key))
            if not os.path.isabs(build_maindir):
                sys.exit('Error : The build_dir_key value must be an absolute path')
            if self.tool.get_key_values(tool_name_key)==None:
                sys.exit('Error : Unknown build type for tool_name_key')
            build_tooldir = self.tool.get_key_values(tool_name_key)
            return build_maindir, build_tooldir
                
        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 'build_dir_sim'   key in the self.tool dictionary
                'synth' uses the 'build_dir_synth' key in the self.tool dictionary
                
            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 tool_name_key value as subdirectory
                - the library name as library subdirectory
            """
            if lib_dicts==None: lib_dicts=self.libs.dicts
            build_maindir, build_tooldir = 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(os.path.join(build_maindir, build_tooldir, lib_name))  # 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==None: lib_names=self.lib_names
            lib_dicts = self.libs.get_dicts('hdl_lib_name', lib_names)
            for lib_dict in cm.listify(lib_dicts):
                lib_name = lib_dict['hdl_lib_name']
                use_libs = self.derive_all_use_libs(build_type, lib_name)
                lib_order = self.derive_lib_order(build_type, use_libs)
                file_name = lib_name + '_lib_order.txt'
                file_path = self.get_lib_build_dirs('sim', lib_dicts=lib_dict)
                cm.mkdir(file_path)
                filePathName = os.path.join(file_path, file_name)
                with open(filePathName, 'w') as fp:
                    for lib in lib_order:
                        fp.write('%s ' % lib)
    
        def read_hdl_libraries_technology_file(self, technologyName, filePath=None):
            """Read the list of technology HDL libraries from a file.
            
               Arguments:
               - technologyName : refers to the hdl_libraries_<technologyName>.txt file
               - filePath       : path to hdl_libraries_<technologyName>.txt, when None then the file is
                                  read in the default toolRootDir
            """
            fileName = 'hdl_libraries_' + technologyName + '.txt'                  # use fixed file name format
            if filePath==None:
                toolSubDir = self.tool.get_key_values('tool_name_synth')
                fileNamePath=os.path.join(self.toolRootDir, toolSubDir, fileName)  # default file path
            else:
                fileNamePath=os.path.join(filePath, fileName)                      # specified file path
            tech_dict = self.tool.read_dict_file(fileNamePath)
            return tech_dict
        
        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
               tool_name_<build_type> key value from the hdltool.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      : one or more HDL libraries
            """
            if lib_names==None: lib_names=self.lib_names
            lib_dicts = self.libs.get_dicts(key='hdl_lib_name', values=lib_names)
            tool_name_key = 'tool_name_' + build_type
            tool_name_value = self.tool.get_key_values(tool_name_key)
            tool_name_copy_key = tool_name_value + '_copy_files'
            for lib_dict in cm.listify(lib_dicts):
                if tool_name_copy_key in lib_dict:
                    lib_path = self.libs.get_filePath(lib_dict)
                    build_path = self.get_lib_build_dirs(build_type, lib_dicts=lib_dict)
                    cm.mkdir(build_path)
                    key_values = lib_dict[tool_name_copy_key].split()
                    sources = key_values[0::2]
                    destinations = key_values[1::2]
                    file_io = zip(sources, destinations)
                    for fpn_io in file_io:
                        sourcePathName = cm.expand_file_path_name(fpn_io[0], lib_path)
                        buildPath = cm.expand_file_path_name(fpn_io[1], build_path)
                        if os.path.isfile(sourcePathName):
                            shutil.copy(sourcePathName, buildPath)           # copy file
                        else:
                            if os.path.exists(buildPath):
                                shutil.rmtree(buildPath)
                            shutil.copytree(sourcePathName, buildPath)       # copy directory tree
    
        
    if __name__ == '__main__':
        # Mode
        # 0 = Read dictionary info from all HDL tool and library configuration files and derive the compile order
        # 1 = Change a key value in all hdllib.cfg dict files
        # 2 = Insert a new key = value pair in all hdllib.cfg dict files at the specified line number
        # 3 = Insert a new key = value pair in all hdllib.cfg dict files just before an already existing key
        # 4 = Rename a key in all hdllib.cfg dict files
        # 5 = Remove a new key = value pair from all hdllib.cfg dict files
        mode = 0
        
        if mode==0:   
            # Read the dictionary info from all HDL tool and library configuration files in the current directory and the sub directories
            technologyNames = []
            technologyNames = ['ip_stratixiv']
            hdl = HdlConfig(toolRootDir=os.path.expandvars('$RADIOHDL/tools'), libFileName='hdllib.cfg', toolFileName='hdltool.cfg', technologyNames=technologyNames)
        
            print '#'
            print '# HdlConfig:'
            print '#'
            for i, p in enumerate(hdl.libs.filePathNames):
                print i, p
                d = hdl.libs.dicts[i]
                for k,v in d.iteritems():
                    print k, '=', v
                print ''
        
            print ''
            print 'tool = ', hdl.tool.filePathNames[0]
            
            print ''
            print 'lib paths'
            for p in hdl.libs.filePaths:
                print '    ', p
                
            print ''
            print 'lib paths names'
            for p in hdl.libs.filePathNames:
                print '    ', p
                
            print ''
            print 'lib_names        = ', hdl.lib_names
            print 'derive_lib_order for sim : ', hdl.derive_lib_order('sim')
            print 'derive_lib_order for synth : ', hdl.derive_lib_order('synth')
            
            print ''
            print 'get_lib_build_dirs for simulation:'
            for sim_dir in hdl.get_lib_build_dirs('sim'):
                print '    ', sim_dir
            
            print ''    
            if hdl.libRootDir=='RADIOHDL':
                #use_libs = hdl.derive_all_use_libs('sim', 'unb1_minimal')
                #use_libs = hdl.derive_all_use_libs('sim', 'dp')
                #use_libs = hdl.derive_all_use_libs('sim', 'tech_xaui')
                use_libs = hdl.derive_all_use_libs('sim', 'unb1_test_10GbE')
                use_libs = hdl.derive_all_use_libs('sim', 'tech_ddr')
                print 'derive_all_use_libs = ', use_libs
                lib_order = hdl.derive_lib_order('sim', use_libs)
                print 'derive_lib_order = ', lib_order
            if hdl.libRootDir=='UNB':
                use_libs = hdl.derive_all_use_libs('sim', 'unb_minimal')
                use_libs = hdl.derive_all_use_libs('sim', 'dp')
                print 'derive_all_use_libs = ', use_libs
                lib_order = hdl.derive_lib_order('sim', use_libs)
                print 'derive_lib_order = ', lib_order
        
        if mode==1:
            key = 'build_dir_synth'
            new_value = '$HDL_BUILD_DIR'
            # Read the dictionary info from all HDL tool and library configuration files in the current directory and the sub directories
            hdl = HdlConfig(toolRootDir=os.path.expandvars('$RADIOHDL/tools'), libFileName='hdllib.cfg', toolFileName='hdltool.cfg', technologyNames=[])
            for p in hdl.libs.filePathNames:
                 hdl.libs.change_key_value_in_dict_file(p, key, new_value)
    
        if mode==2:
            insert_key = 'hdl_lib_technology'
            insert_value = ''
            insertLineNr = 4
            # Read the dictionary info from all HDL tool and library configuration files in the current directory and the sub directories
            hdl = HdlConfig(toolRootDir=os.path.expandvars('$RADIOHDL/tools'), libFileName='hdllib.cfg', toolFileName='hdltool.cfg', technologyNames=[])
            for p in hdl.libs.filePathNames:
                 hdl.libs.insert_key_in_dict_file_at_line_number(p, insert_key, insert_value, insertLineNr)
    
        if mode==3:
            insert_key = 'hdl_lib_uses_sim'
            insert_value = '\n'
            insert_beforeKey = 'hdl_lib_technology'
            # Read the dictionary info from all HDL tool and library configuration files in the current directory and the sub directories
            hdl = HdlConfig(toolRootDir=os.path.expandvars('$RADIOHDL/tools'), libFileName='hdllib.cfg', toolFileName='hdltool.cfg', technologyNames=[])
            for p in hdl.libs.filePathNames:
                 hdl.libs.insert_key_in_dict_file_before_another_key(p, insert_key, insert_value, insert_beforeKey)
    
        if mode==4:
            old_key = 'hdl_lib_uses'
            new_key = 'hdl_lib_uses_synth'
            # Read the dictionary info from all HDL tool and library configuration files in the current directory and the sub directories
            hdl = HdlConfig(toolRootDir=os.path.expandvars('$RADIOHDL/tools'), libFileName='hdllib.cfg', toolFileName='hdltool.cfg', technologyNames=[])
            for p in hdl.libs.filePathNames:
                 hdl.libs.rename_key_in_dict_file(p, old_key, new_key)
                 
        if mode==5:
            remove_key = 'build_dir_synth'
            # Read the dictionary info from all HDL tool and library configuration files in the current directory and the sub directories
            hdl = HdlConfig(toolRootDir=os.path.expandvars('$RADIOHDL/tools'), libFileName='hdllib.cfg', toolFileName='hdltool.cfg', technologyNames=[])
            for p in hdl.libs.filePathNames:
                 hdl.libs.remove_key_from_dict_file(p, remove_key)