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

Subversion Repositories radiohdl

[/] [radiohdl/] [trunk/] [core/] [quartus_config] - Rev 4

Compare with Previous | Blame | View Log

#! /usr/bin/env python3
###############################################################################
#
# 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 Quartus synthesis targets.

   Usage:
   > python ${RADIOHDL_GEAR}/core/quartus_config -t unb1
"""

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


class QuartusConfig(hdl_libraries_wizard.HdlLibrariesWizard):

    def __init__(self, toolRootDir, toolFileName, libFileName='hdllib.cfg'):
        """Get Quartus 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.

           Arguments:
           - toolRootDir     : Root directory from where the hdl_buildset_<buildset>.cfg file is searched for.
           - toolFileName    : 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.

           The technologyNames parameter is defined in the hdl_buildset_<buildset>.cfg file. All generic HDL libraries and these
           technology specific libraries are kept.

           Files:
           - 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.

           - <lib_name>.qpf : Quartus project file (QPF) for a certain HDL library based on the hdllib.cfg. The file is created by
                              create_quartus_project_file().

           - <lib_name>.qsf : Quartus settings file (QSF) for a certain HDL library based on the hdllib.cfg. The file is created by
                              create_quartus_settings_file(). There is one QSF per Quartus synthesis project.
        """
        print("QuartusConfig(toolRootDir=%s, toolFileName=%s, libFileName=%s)" % (toolRootDir, toolFileName, libFileName))
        libFileSections = ['quartus_project_file']
        hdl_libraries_wizard.HdlLibrariesWizard.__init__(self, toolRootDir, toolFileName, libFileName, libFileSections)

    def create_quartus_ip_lib_file(self, lib_names=None):
        """Create the Quartus IP file <hdl_lib_name>_lib.qip for all HDL libraries. The <hdl_lib_name>.qip file contains the list of files that are given
           by the synth_files key and the quartus_*_file keys.

           Note:
           . Use post fix '_lib' in QIP file name *_lib.qip to avoid potential conflict with *.qip that may come with the IP.
           . The HDL library *_lib.qip files contain all files that are listed by the synth_files key. Hence when these qip files are included then
             the Quartus project will analyse all files even if there entity is not instantiated in the design. This is fine, it is unnecessary
             to parse the hierarchy of the synth_top_level_entity VHDL file to find and include only the source files that are actually used.

           Arguments:
           - lib_names      : one or more HDL libraries
        """
        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:
            # Open qip
            lib_name = lib_dict['hdl_lib_name']
            qip_name = lib_name + '_lib.qip'
            qip_path = self.get_lib_build_dirs('synth', lib_dicts=lib_dict)
            cm.mkdir(qip_path)
            qipPathName = cm.expand_file_path_name(qip_name, qip_path)
            with open(qipPathName, 'w') as fp:
                if lib_dict.get_value('synth_files'):
                    fp.write('# synth_files\n')
                    synth_files = lib_dict['synth_files'].split()
                    for fn in synth_files:
                        filePathName = cm.expand_file_path_name(fn, lib_dict.location)

                        file_ext = fn.split('.')[-1]
                        if file_ext == 'vhd' or file_ext == 'vhdl':
                            file_type = 'VHDL_FILE'
                        elif file_ext == 'v':
                            file_type = 'VERILOG_FILE'
                        else:
                            print('\nERROR - Undefined file extension in synth_files:', fn)
                            sys.exit()

                        fp.write('set_global_assignment -name %s %s -library %s\n' % (file_type, filePathName, lib_name + '_lib'))

                if lib_dict.get_value('quartus_vhdl_files'):
                    fp.write('\n')
                    fp.write('# quartus_vhdl_files\n')
                    quartus_vhdl_files = lib_dict['quartus_vhdl_files'].split()
                    for fn in quartus_vhdl_files:
                        filePathName = cm.expand_file_path_name(fn, lib_dict.location)

                        file_ext = fn.split('.')[-1]
                        if file_ext == 'vhd' or file_ext == 'vhdl':
                            file_type = 'VHDL_FILE'
                        elif file_ext == 'v':
                            file_type = 'VERILOG_FILE'
                        else:
                            print('\nERROR - Undefined file extension in quartus_vhdl_files:', fn)
                            sys.exit()

                        fp.write('set_global_assignment -name VHDL_FILE %s -library %s\n' % (filePathName, lib_name + '_lib'))

                if lib_dict.get_value('quartus_qip_files'):
                    fp.write('\n')
                    fp.write('# quartus_qip_files\n')
                    quartus_qip_files = lib_dict['quartus_qip_files'].split()
                    for fn in quartus_qip_files:
                        filePathName = cm.expand_file_path_name(fn, lib_dict.location)
                        fp.write('set_global_assignment -name QIP_FILE %s\n' % filePathName)

                if lib_dict.get_value('quartus_tcl_files'):
                    fp.write('\n')
                    fp.write('# quartus_tcl_files\n')
                    quartus_tcl_files = lib_dict['quartus_tcl_files'].split()
                    for fn in quartus_tcl_files:
                        filePathName = cm.expand_file_path_name(fn, lib_dict.location)
                        fp.write('set_global_assignment -name SOURCE_TCL_SCRIPT_FILE %s\n' % filePathName)

                if lib_dict.get_value('quartus_sdc_files'):
                    fp.write('\n')
                    fp.write('# quartus_sdc_files\n')
                    quartus_sdc_files = lib_dict['quartus_sdc_files'].split()
                    for fn in quartus_sdc_files:
                        filePathName = cm.expand_file_path_name(fn, lib_dict.location)
                        fp.write('set_global_assignment -name SDC_FILE %s\n' % filePathName)
        print("Created {} .qip files".format(len(lib_dicts)))

    def create_quartus_project_file(self, lib_names=None):
        """Create the Quartus project file (QPF) for all HDL libraries that have a toplevel entity key synth_top_level_entity.

           Note:
           . Default if the synth_top_level_entity key is defined but left empty then the top level entity has the same name as the lib_name in hdl_lib_name.
             Otherwise synth_top_level_entity can specify another top level entity name in the library. Each HDL library can only have one Quartus project
             file
           . The project revision has the same name as the lib_name and will result in a <lib_name>.sof FPGA image file.
           . For each additional revision a subdirectory can be used.
             This subdirectory can be named 'revisions/' and lists a number of revisions as subdirectories. Each revision will have a separate hdllib.cfg file and a
             .vhd file with the toplevel entity. The toplevel .vhd file specifies the <g_design_name> for the revision in the generics.

           Arguments:
           - lib_names      : one 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)
        syn_dicts = self.libs.get_configfiles(key='synth_top_level_entity', values=None, user_configfiles=lib_dicts)
        for syn_dict in syn_dicts:
            # Open qpf for each HDL library that has a synth_top_level_entity
            lib_name = syn_dict['hdl_lib_name']
            qpf_name = lib_name + '.qpf'
            qpf_path = self.get_lib_build_dirs('synth', lib_dicts=syn_dict)
            cm.mkdir(qpf_path)
            qpfPathName = cm.expand_file_path_name(qpf_name, qpf_path)
            with open(qpfPathName, 'w') as fp:
                fp.write('PROJECT_REVISION = "%s"\n' % lib_name)
        print("Created {} .qpf files".format(len(syn_dicts)))

    def create_quartus_settings_file(self, lib_names=None):
        """Create the Quartus settings file (QSF) for all HDL libraries that have a toplevel entity key synth_top_level_entity.

           Note:
           . No support for revisions, so only one qsf per qpf

           Arguments:
           - lib_names      : one 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)
        syn_dicts = self.libs.get_configfiles(key='synth_top_level_entity', values=None, user_configfiles=lib_dicts)
        for syn_dict in syn_dicts:
            # Open qsf for each HDL library that has a synth_top_level_entity
            lib_name = syn_dict['hdl_lib_name']
            top_level_entity = syn_dict['synth_top_level_entity']
            if top_level_entity == '':
                top_level_entity = lib_name
            qsf_path = self.get_lib_build_dirs('synth', lib_dicts=syn_dict)
            cm.mkdir(qsf_path)

            # One qsf per lib_name
            qsf_name = lib_name + '.qsf'
            qsfPathName = cm.expand_file_path_name(qsf_name, qsf_path)
            with open(qsfPathName, 'w') as fp:
                fp.write('# synth_top_level_entity\n')
                fp.write('set_global_assignment -name TOP_LEVEL_ENTITY %s\n' % top_level_entity)

                fp.write('\n')
                fp.write('# quartus_qsf_files\n')
                quartus_qsf_files = syn_dict['quartus_qsf_files'].split()
                for fn in quartus_qsf_files:
                    filePathName = cm.expand_file_path_name(fn, syn_dict.location)
                    fp.write('set_global_assignment -name SOURCE_TCL_SCRIPT_FILE %s\n' % filePathName)

                fp.write('\n')
                fp.write('# All used HDL library *_lib.qip files in order with top level last\n')
                use_lib_order = self.derive_lib_order('synth', lib_name)
                # use_lib_dicts = self.libs.get_configfiles('hdl_lib_name', values=use_lib_order)    # uses original libs.dicts order, but
                use_lib_dicts = self.get_lib_dicts_from_lib_names(lib_names=use_lib_order)    # must preserve use_lib_order order to ensure that top level design qip with sdc file is include last in qsf
                for lib_dict in cm.listify(use_lib_dicts):
                    qip_path = self.get_lib_build_dirs('synth', lib_dicts=lib_dict)
                    qip_name = lib_dict['hdl_lib_name'] + '_lib.qip'
                    qipPathName = cm.expand_file_path_name(qip_name, qip_path)
                    fp.write('set_global_assignment -name QIP_FILE %s\n' % qipPathName)

                if syn_dict.get_value('quartus_ip_files'):
                    # print(syn_dict['quartus_ip_files'])
                    fp.write('\n')
                    fp.write('# All used HDL library *.ip files in order with top level last\n')
                    quartus_ip_files = syn_dict['quartus_ip_files'].split()
                    for fn in quartus_ip_files:
                        filePathName = cm.expand_file_path_name(fn)
                        fp.write('set_global_assignment -name IP_FILE %s\n' % filePathName)
                
                fp.write('\n')
        print("Created {} .qsf files".format(len(syn_dicts)))


if __name__ == '__main__':
    # Parse command line arguments
    buildsetSelect = sorted([cfgfile[13:-4] for cfgfile in listdir(os.getenv('RADIOHDL_CONFIG'))
                             if cfgfile.startswith("hdl_buildset_") and cfgfile.endswith(".cfg")])
    argparser = ArgumentParser(description='Quartus_config creates/updates all your quartus projectfiles.')
    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)
        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
    qsyn = QuartusConfig(toolRootDir=os.getenv('RADIOHDL_CONFIG'),
                         toolFileName=args.buildsetFile,
                         libFileName='hdllib.cfg')

    if args.verbosity >= 2:
        print('#')
        print('# QuartusConfig:')
        print('#')
        print('')
        print('HDL library paths that are found in $%s:' % qsyn.libRootDirs)
        for p in sorted(qsyn.libs.configfiles.values()):
            print('    ', p.location)

    if args.verbosity >= 1:
        print('')
        print('HDL libraries with a top level entity for synthesis that are found in $%s:' % qsyn.libRootDirs)
        print('    %-40s' % 'HDL library', ': Top level entity')
        syn_dicts = qsyn.libs.get_configfiles(key='synth_top_level_entity')
        for d in syn_dicts:
            if d['synth_top_level_entity'] == '':
                print('    %-40s' % d['hdl_lib_name'], ':', d['hdl_lib_name'])
            else:
                print('    %-40s' % d['hdl_lib_name'], ':', d['synth_top_level_entity'])

    print('')
    print('Create Quartus IP library qip files for all HDL libraries in $%s.'
          % qsyn.libRootDirs)
    qsyn.create_quartus_ip_lib_file()

    print('')
    print('Copy Quartus directories and files from HDL library source tree to build_dir for all HDL libraries that are found in $%s.'
          % qsyn.libRootDirs)
    qsyn.copy_files('synth')

    print('')
    print('Create Quartus project files (QPF) for technology %s and all HDL libraries with a top level entity for synthesis that are found in $%s.'
          % (qsyn.technologyNames, qsyn.libRootDirs))
    qsyn.create_quartus_project_file()

    print('')
    print('Create Quartus settings files (QSF) for technology %s and all HDL libraries with a top level entity for synthesis that are found in $%s.'
          % (qsyn.technologyNames, qsyn.libRootDirs))
    qsyn.create_quartus_settings_file()

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.