Subversion Repositories radiohdl

[/] [radiohdl/] [trunk/] [base/] [modelsim_config] - Rev 2

Compare with Previous | Blame | View Log

#! /usr/bin/env python
# Copyright (C) 2014
# ASTRON (Netherlands Institute for Radio Astronomy) <>
# 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
# 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 <>.

"""HDL configuration for building Modelsim simulation targets.

   > python $RADIOHDL/tools/oneclick/base/ -t unb1

import sys
import os.path
from os             import listdir
from argparse       import ArgumentParser
import common as cm
import hdl_libraries_wizard

class ModelsimConfig(hdl_config.HdlLibrariesWizard):

    def __init__(self, toolRootDir, buildsetFile, libFileName):
        """Get Modelsim tool info from toolRootDir and all HDL library info from libRootDir.
           This class uses the default keys and the keys from the libFileSections in the libFileName config file.
           - toolRootDir     : Root directory from where the hdl_buildset_<buildset>.cfg file is searched for.
           - buildsetFile    : Default HDL tools configuration file name
           - libFileName     : Default HDL library configuration file name
           The libRootDir is defined in the hdl_buildset_<buildset>.cfg file and is the root directory from where the hdllib.cfg
           files are searched for.
           - hdl_buildset_<buildset>.cfg : HDL tool configuration dictionary file. One central file per buildset.
           - hdllib.cfg : HDL library configuration dictionary file. One file for each HDL library.
           - modelsim_project_files.txt
             The modelsim_project_files.txt file is a dictionary file with the list the Modelsim project files for all HDL
             libraries that were found in the libRootDir. The keys are the library names and the values are the paths to the
             corresponding modelsim project files. The modelsim_project_files.txt file is created by
             create_modelsim_project_files_file() and is read by the TCL file in Modelsim. Creating the file in
             Python and then reading this in TCL makes the much simpler.
           - <lib_name>.mpf : Modelsim project file for a certain HDL library based on the hdllib.cfg. The file is created by
           - <lib_name>_lib_order.txt
             The <lib_name>_lib_order.txt file contains the library compile order for a certain HDL library. The files are
             created by create_lib_order_files() in the same build directory as where the Modelsim project file is stored.
             The <lib_name>_lib_order.txt files are read by the TCL file in Modelsim. Creating the files in Python
             and then reading them in TCL makes the much simpler.
        hdl_config.HdlLibrariesWizard.__init__(self, toolRootDir, buildsetFile, libFileName, libFileSections)

    def read_compile_order_from_mpf(self, mpfPathName):
        """Utility to read the compile order of the project files from an existing <mpfPathName>.mpf."""
        # read <mpfPathName>.mpf to find all project files
        project_file_indices = []
        project_file_names = []
        with open(mpfPathName, 'r') as fp:
            for line in fp:
                words = line.split()
                if len(words)>0:
                    key = words[0]
                    if key.find('Project_File_')>=0 and key.find('Project_File_P_')==-1:
        # read <mpfPathName>.mpf again to find compile order for the project files
        compile_order = range(len(project_file_names))
        with open(mpfPathName, 'r') as fp:
            for line in fp:
                words = line.split()
                if len(words)>0:
                    key = words[0]
                    if key.find('Project_File_P_')>=0:
                        project_file_index = project_file_indices.index(key[len('Project_File_P_'):])
                        project_file_name = project_file_names[project_file_index]
                        k = words.index('compile_order')
                        k = int(words[k+1])
        return compile_order

    def read_hdl_libraries_technology_file(self, technologyName, filePath=None):
        """Read the list of technology HDL libraries from a file.
           - 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:
            toolDir    = os.path.expandvars('$HDL_BUILD_DIR')
            toolSubDir = self.buildset['buildset_name']
            fileNamePath=join(toolDir, toolSubDir, fileName)          # default file path
            fileNamePath=join(filePath, fileName)                     # specified file path
        tech_dict = ConfigFile(fileNamePath).content
        return tech_dict
    def create_modelsim_lib_compile_ip_files(self, lib_names=None):
        Create the '<lib_name>_lib_compile_ip.txt' file 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 in Modelsim to know which IP needs to be compiled before the library is compiled.
        if lib_names==None:

        count     = 0
        lib_dicts = self.libs.get_configfiles(key='hdl_lib_name', values=lib_names)
        for lib_dict in lib_dicts:
            if 'modelsim_compile_ip_files' in lib_dict.content:
                count += 1
                compile_ip_files = lib_dict['modelsim_compile_ip_files'].split()
                lib_name = lib_dict['hdl_lib_name']
                file_name = lib_name + '_lib_compile_ip.txt'
                file_path = self.get_lib_build_dirs('sim', lib_dicts=lib_dict)
                filePathName = os.path.join(file_path, file_name)
                with open(filePathName, 'w') as fp:
                    for fpn in compile_ip_files:
                        # Write the expanded file path name for <lib_name>_lib_compile_ip.txt so that it can be executed directly from its location in SVN using the Modelsim "do"-command in the
                        # An alternative would be to write the basename, so only <lib_name>_lib_compile_ip.txt, but that would require copying the basename file to the mpf build directory
                        efpn = os.path.expandvars(fpn)
                        fp.write('%s ' % efpn)
        print "Created {} compile-ip files".format(count)

    def simulation_configuration(self, list_mode=False):
        """Prepare settings for simulation configuration.
           The output format is string or list, dependent on list_mode.
           Return tuple of project_sim_p_defaults, project_sim_p_search_libraries, project_sim_p_otherargs, project_sim_p_optimization.
        # project_sim_p_defaults
        project_sim_p_defaults = 'Generics {} timing default -std_output {} -nopsl 0 +notimingchecks 0 selected_du {} -hazards 0 -sdf {} ok 1 -0in 0 -nosva 0 +pulse_r {} -absentisempty 0 -multisource_delay {} +pulse_e {} vopt_env 1 -coverage 0 -sdfnoerror 0 +plusarg {} -vital2.2b 0 -t default -memprof 0 is_vopt_flow 0 -noglitch 0 -nofileshare 0 -wlf {} -assertdebug 0 +no_pulse_msg 0 -0in_options {} -assertfile {} -sdfnowarn 0 -Lf {} -std_input {}'
        # project_sim_p_search_libraries
        if list_mode:
            project_sim_p_search_libraries = self.buildset['modelsim_search_libraries'].split()
            project_sim_p_search_libraries = '-L {}'
            if 'modelsim_search_libraries' in self.buildset:
                project_sim_p_search_libraries = '-L {'
                for sl in self.buildset['modelsim_search_libraries'].split():
                    project_sim_p_search_libraries += sl
                    project_sim_p_search_libraries += ' '
                project_sim_p_search_libraries += '}'
        # project_sim_p_otherargs
        # Note:
        #   E.g. the vsim-8684 load warning does not occur when the simulation is loaded via double click, but it
        #   does occur when the simulation is relaoded via the command line, because in the command line history
        #   the +nowarn8684 is then for some reason not preserved by Modelsim.
        otherargs = ''
        otherargs = '+nowarn8684 +nowarn8683 -quiet'
        otherargs = '+nowarn8684 +nowarn8683'
        otherargs = '+nowarn8684 +nowarn8683 +nowarnTFMPC +nowarnPCDPC'  # nowarn on verilog IP connection mismatch warnings
        if list_mode:
            project_sim_p_otherargs = otherargs.split()
            project_sim_p_otherargs = 'OtherArgs {' + otherargs + '}'
        # project_sim_p_optimization
        project_sim_p_optimization = 'is_vopt_opt_used 2'  # = when 'Enable optimization' is not selected in GUI
        project_sim_p_optimization = 'is_vopt_opt_used 1 voptargs {OtherVoptArgs {} timing default VoptOutFile {} -vopt_keep_delta 0 -0in 0 -fvopt {} VoptOptimize:method 1 -vopt_00 2 +vopt_notimingcheck 0 -Lfvopt {} VoptOptimize:list .vopt_opt.nb.canvas.notebook.cs.page1.cs.g.spec.listbox -Lvopt {} +vopt_acc {} VoptOptimize .vopt_opt.nb.canvas.notebook.cs.page1.cs -vopt_hazards 0 VoptOptimize:Buttons 0InOptionsWgt .vopt_opt.nb.canvas.notebook.cs.page3.cs.zf.ze -0in_options {}}' # = when 'Enable optimization' is selected in GUI for full visibility
        return project_sim_p_defaults, project_sim_p_search_libraries, project_sim_p_otherargs, project_sim_p_optimization

    def create_modelsim_project_file(self, lib_names=None):
        Create the Modelsim project file for all technology libraries and RTL HDL libraries.
        - lib_names       : one or more HDL libraries
        Library mapping:
        - Technology libraries that are available, but not used are mapped to work.
        - Unavailable libraries are also mapped to work. The default library clause name is <lib_name>
          with postfix '_lib'. This is a best effort guess, because it is impossible to know the library clause name
          for an unavailable library. If the best effort guess is not suitable, then the workaround is to create a
          place holder directory with hdllib.cfg that defines the actual library clause name as it appears in the
          VHDL for the unavailable HDL library. unavailable library names occur when e.g. a technology IP library
          is not available in the toolRootDir because it is not needed, or it may indicate a spelling error.
        if lib_names==None:

        lib_dicts = self.libs.get_configfiles(key='hdl_lib_name', values=lib_names)
        print "SELF.BUILDSET=", self.buildset
        for lib_dict in lib_dicts:
            # Open mpf
            lib_name = lib_dict['hdl_lib_name']
            mpf_name = lib_name + '.mpf'
            mpf_path = self.get_lib_build_dirs('sim', lib_dicts=lib_dict)
            mpfPathName = os.path.join(mpf_path, mpf_name)
            with open(mpfPathName, 'w') as fp:
                # Write [Library] section for all used libraries

                # . map used vendor technology libs to their target directory
                for technologyName in self.technologyNames:
                    tech_dict = self.read_hdl_libraries_technology_file(technologyName)
                    for lib_clause, lib_work in tech_dict.iteritems():
                        fp.write('%s = %s\n' % (lib_clause, lib_work))

                # . not used vendor technology libs are not compiled but are mapped to work to avoid compile error when mentioned in the LIBRARY clause
                for removed_lib in sorted(self.removed_libs):
                    fp.write('%s = work\n' % self.removed_libs[removed_lib]['hdl_library_clause_name'])

                # . unavailable used libs are not compiled but are mapped to work to avoid compile error when mentioned in the LIBRARY clause
                for unavailable_use_name in sorted(self.unavailable_use_libs):
                    # if the unavailable library is not in the dictionary of disclosed unavailable library clause names, then assume that the library clause
                    # name has the default postfix '_lib'.
                    if unavailable_use_name in self.disclosed_library_clause_names:
                        fp.write('%s = work\n' % self.disclosed_library_clause_names[unavailable_use_name])
                        fp.write('%s_lib = work\n' % unavailable_use_name)

                # . all used libs for this lib_name
                use_lib_names          = self.derive_all_use_libs('sim', lib_name)
                use_lib_dicts          = self.libs.get_configfiles(key='hdl_lib_name', values=use_lib_names)
                use_lib_build_sim_dirs = self.get_lib_build_dirs('sim', lib_dicts=use_lib_dicts)
                use_lib_clause_names   = self.libs.get_key_values('hdl_library_clause_name', use_lib_dicts)
                for lib_clause, lib_dir in zip(use_lib_clause_names, cm.listify(use_lib_build_sim_dirs)):
                    lib_work = os.path.join(lib_dir, 'work')
                    fp.write('%s = %s\n' % (lib_clause, lib_work))

                # . work
                fp.write('work = work\n')

                # . others modelsim default libs
                model_tech_dir = os.path.expandvars(self.buildset['modelsim_dir'])
                fp.write('others = %s\n' % os.path.join(model_tech_dir, 'modelsim.ini'))
                # Write [Project] section for all used libraries
                fp.write('Project_Version = 6\n')  # must be >= 6 to fit all
                fp.write('Project_DefaultLib = work\n')
                fp.write('Project_SortMethod = unused\n')
                # - project files
                synth_files      = lib_dict['synth_files'].split()
                test_bench_files = lib_dict['test_bench_files'].split()
                project_files    = synth_files + test_bench_files
                if 'modelsim_compile_ip_files' in lib_dict.content:
                    compile_ip_files = lib_dict['modelsim_compile_ip_files'].split()
                    project_files += compile_ip_files
                fp.write('Project_Files_Count = %d\n' % len(project_files))
                for i, fn in enumerate(project_files):
                    filePathName = cm.expand_file_path_name(fn, lib_dict.location)
                    fp.write('Project_File_%d = %s\n' % (i, filePathName))

                project_file_p_defaults_hdl     = 'vhdl_novitalcheck 0 group_id 0 cover_nofec 0 vhdl_nodebug 0 vhdl_1164 1 vhdl_noload 0 vhdl_synth 0 vhdl_enable0In 0 vlog_1995compat 0 last_compile 0 vhdl_disableopt 0 cover_excludedefault 0 vhdl_vital 0 vhdl_warn1 1 vhdl_warn2 1 vhdl_explicit 1 vhdl_showsource 0 cover_covercells 0 vhdl_0InOptions {} vhdl_warn3 1 vlog_vopt {} cover_optlevel 3 voptflow 1 vhdl_options {} vhdl_warn4 1 toggle - ood 0 vhdl_warn5 1 cover_noshort 0 compile_to work cover_nosub 0 dont_compile 0 vhdl_use93 2002 cover_stmt 1'
                project_file_p_defaults_vhdl    = 'file_type vhdl'
                project_file_p_defaults_verilog = 'file_type verilog'
                project_file_p_defaults_tcl     = 'last_compile 0 compile_order -1 file_type tcl group_id 0 dont_compile 1 ood 1'

                project_folders = []
                offset = 0

                nof_synth_files = len(synth_files)
                if nof_synth_files>0:
                    for i in range(nof_synth_files):  

                        # Add file type specific settings
                        file_ext = synth_files[i].split('.')[-1]
                        if file_ext=='vhd' or file_ext=='vhdl':
                            project_file_p_defaults_file_specific = project_file_p_defaults_vhdl
                        elif file_ext=='v':
                             project_file_p_defaults_file_specific = project_file_p_defaults_verilog
                             print '\nERROR - Undefined file extension in synth_files:', lib_name, synth_files[i]

                        fp.write('Project_File_P_%d = folder %s compile_order %d %s\n' % (offset+i, project_folders[-1], offset+i, project_file_p_defaults_hdl+' '+project_file_p_defaults_file_specific))
                offset = nof_synth_files

                nof_test_bench_files = len(test_bench_files)
                if nof_test_bench_files>0:
                    for i in range(nof_test_bench_files):

                        # Add file type specific settings
                        file_ext = test_bench_files[i].split('.')[-1]
                        if file_ext=='vhd' or file_ext=='vho' or file_ext=='vhdl':
                            project_file_p_defaults_file_specific = project_file_p_defaults_vhdl
                        elif file_ext=='v':
                            project_file_p_defaults_file_specific = project_file_p_defaults_verilog
                            print '\nERROR - Undefined file extension in test_bench_files:', lib_name, test_bench_files[i]

                        fp.write('Project_File_P_%d = folder %s compile_order %d %s\n' % (offset+i, project_folders[-1], offset+i, project_file_p_defaults_hdl+' '+project_file_p_defaults_file_specific))
                offset += nof_test_bench_files

                if 'modelsim_compile_ip_files' in lib_dict.content:
                    nof_compile_ip_files = len(compile_ip_files)
                    if nof_compile_ip_files>0:
                        for i in range(nof_compile_ip_files):
                            fp.write('Project_File_P_%d = folder %s compile_order %d %s\n' % (offset+i, project_folders[-1], offset+i, project_file_p_defaults_tcl))
                    offset += nof_compile_ip_files
                # - project folders
                fp.write('Project_Folder_Count = %d\n' % len(project_folders))
                for i, fd in enumerate(project_folders):
                    fp.write('Project_Folder_%d = %s\n' % (i, fd))
                    fp.write('Project_Folder_P_%d = folder {Top Level}\n' % i)
                # - simulation configurations
                fp.write('Project_Sim_Count = %d\n' % len(test_bench_files))
                project_sim_p_defaults, project_sim_p_search_libraries, project_sim_p_otherargs, project_sim_p_optimization = self.simulation_configuration()
                for i, fn in enumerate(test_bench_files):
                    fName = os.path.basename(fn)
                    tbName = os.path.splitext(fName)[0]
                    fp.write('Project_Sim_%d = %s\n' % (i, tbName))
                for i, fn in enumerate(test_bench_files):
                    fName = os.path.basename(fn)
                    tbName = os.path.splitext(fName)[0]
                    fp.write('Project_Sim_P_%d = folder {Top Level} additional_dus work.%s %s %s %s %s\n' % (i, tbName, project_sim_p_defaults, project_sim_p_search_libraries, project_sim_p_otherargs, project_sim_p_optimization))
                # Write [vsim] section
                fp.write('RunLength = 0 ps\n')
                fp.write('resolution = 1fs\n')
                fp.write('IterationLimit = 5000\n')       # According to 'verror 3601' the default is 5000, typically 100 is enough, but e.g. the ip_stratixiv_phy_xaui_0 requires more.
                fp.write('DefaultRadix = decimal\n')
        print "Created {} project files".format(len(lib_dicts))
    def create_modelsim_project_files_file(self, lib_names=None):
        """Create file with list of the Modelsim project files for all HDL libraries.
           - lib_names  : one or more HDL libraries
        fileName = 'modelsim_project_files.txt'                                              # use fixed file name
        build_maindir, build_buildsetdir, build_tooldir, project_deeper_subdir = self.get_tool_build_dir('sim')
        fileNamePath=os.path.join(build_maindir, build_buildsetdir, build_tooldir, fileName)  # and use too build dir for file path
        if lib_names==None:
        with open(fileNamePath, 'w') as fp:
            lib_dicts = self.libs.get_configfiles(key='hdl_lib_name', values=lib_names)
            mpf_paths = self.get_lib_build_dirs('sim', lib_dicts=lib_dicts)
            for lib_name, mpf_path in zip(cm.listify(lib_names),cm.listify(mpf_paths)):
                fp.write('%s = %s\n' % (lib_name, mpf_path))
        print "Created project file {}".format(fileNamePath)

if __name__ == '__main__':
    # Mode
    # 0 = Create Modelsim mpf files for all hdllib.cfg
    # 1 = Read compile order from mpf for a single <lib_name> and write itinto the hdllib.cfg.
    #     This is useful to avoid having to manually edit the compile order for an existing $UNB <lib_name>.mpf into the hdllib.cfg.
    #     The compile order is important for the synth_files that need to be in hierarchical order. The test_bench_files are typically
    #     independent so these may be put in alphabetical order. The compile order is read from the <lib_name>.mpf and saved in the
    #     hdllib.cfg. The hdllib.cfg still does need some manual editing to set the proper key and paths.
    mode = 0
    buildsetSelect = sorted([cfgfile[13:-4] for cfgfile in listdir(os.path.expandvars('$HDL_CONFIG_DIR')) 
                                                if cfgfile.startswith("hdl_buildset_") and cfgfile.endswith(".cfg")])
    # Parse command line arguments
    argparser = ArgumentParser(description='Modelsim creates/updates all your modelsim environment(s).')
    argparser.add_argument('buildset',         help='choose buildset %s' % (buildsetSelect))
    argparser.add_argument('-v','--verbosity', required=False, type=int, default=0, help='verbosity >= 0 for more info')
    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
    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
    msim = ModelsimConfig(toolRootDir  = os.path.expandvars('$HDL_CONFIG_DIR'), 
                          buildsetFile = args.buildsetFile,
                          libFileName  = 'hdllib.cfg')
    if mode==0:   
        # Read the dictionary info from all HDL tool and library configuration files in the current directory and the sub directories
        if args.verbosity>=2:
            print '#'
            print '# ModelsimConfig:'
            print '#'
            print ''
            print 'HDL library paths that are found in %s:' % msim.libRootDirs
            for lib in sorted(msim.libs.configfiles.values()):
                print '    ', lib.location
        if args.verbosity>=2:
            print ''
            print 'Build directories for simulation:'
            for sim_dir in msim.get_lib_build_dirs('sim'):
                print '    ', sim_dir

        print ''
        print 'Create library compile order files for simulation...'
        print ''
        print 'Create library compile ip files...'
        print ''
        print 'Create modelsim projects list file...'
        print ''
        print 'Create sub directory in project dir for all HDL libraries that are found in %s...' % msim.libRootDirs
        msim.create_sub_directory_in_build_lib_dir('sim', 'mmfiles')    # should match c_mmf_local_dir_path in mm_file_pkg.vhd
        print ''
        print 'Copy directories and files from HDL library source tree to project dir for all HDL libraries that are found in %s...' % msim.libRootDirs
        print ''
        print 'Create Modelsim Project Files for technology %s and all HDL libraries in %s...' % (msim.technologyNames, msim.libRootDirs)
    if mode==1:
        #for lib_name in ['ado','ap','bf','bist','blp','bp','cdo','cim','cir','cp','cr','dc','eth','fmf','i2c','lvds','pfs','pft2','rcuh','ri','rsp','rsr','rsu','sens','serdes','si','st','tbbi','tdsh']:
        for lib_name in ['tst']:
            # Read compile order from existing <lib_name>.mpf
            # First manually create rudimentary hdllib.cfg file for the library with lib name and clause filled in. Then run this script to get
            # the ordered list of src and tb files. Then manualy edit the hdllib.cfg to put the files at the synth or sim key.
            #mpfPathName = os.path.expandvars('$UNB/Firmware/designs/%s/build/synth/quartus/sopc_%s_sim/%s.mpf' % (lib_name, lib_name, lib_name))
            #mpfPathName = os.path.expandvars('$UNB/Firmware/modules/Lofar/%s/build/sim/modelsim/%s.mpf' % (lib_name, lib_name))
            #mpfPathName = os.path.expandvars('$UNB/Firmware/modules/%s/build/sim/modelsim/%s.mpf' % (lib_name, lib_name))
            mpfPathName = os.path.expandvars('$RSP/%s/build/sim/modelsim/%s.mpf' % (lib_name, lib_name))
            compile_order = msim.read_compile_order_from_mpf(mpfPathName)
            # Append the compile_order list to the lib_name dictionary hdllib.cfg file
            lib_dict = msim.libs.get_configfiles(key='hdl_lib_name', values=lib_name)
            lib_path = msim.libs.get_filePath(lib_dict)
            filePathName = os.path.join(lib_path, 'hdllib.cfg')
            print ''
            print 'Save modelsim compile order for', lib_name, 'in HDL library config file', filePathName
            msim.libs.append_key_to_dict_file(filePathName, 'files', compile_order)

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

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