<commit_before>import logging
import os.path
import os
import platform
import subprocess
import re
import xml.etree.ElementTree as ET
from functools import partial
from edalize.edatool import Edatool

logger = logging.getLogger(__name__)

class Quartus(Edatool):

    argtypes = ['vlogdefine', 'vlogparam', 'generic']

    # Define Standard edition to be our default version
    isPro = False
    makefile_template = {False : "quartus-std-makefile.j2",
                         True  : "quartus-pro-makefile.j2"}
    dse_template = 'quartus-dse.j2'

    @classmethod
    def get_doc(cls, api_ver):
        if api_ver == 0:
            return {'description' : "The Quartus backend supports Intel Quartus Std and Pro editions to build systems and program the FPGA",
                    'members' : [
                        {'name' : 'family',
                         'type' : 'String',
                         'desc' : 'FPGA family (e.g. Cyclone V)'},
                        {'name' : 'device',
                         'type' : 'String',
                         'desc' : 'FPGA device (e.g. 5CSXFC6D6F31C8ES)'},
                        {'name' : 'cable',
                         'type' : 'String',
                         'desc' : "Specifies the FPGA's JTAG programming cable. Use the tool `jtagconfig` to determine the available cables."},
                        {'name' : 'board_device_index',
                         'type' : 'String',
                         'desc' : "Specifies the FPGA's device number in the JTAG chain. The device index specifies the device where the flash programmer looks for the Nios® II JTAG debug module. JTAG devices are numbered relative to the JTAG chain, starting at 1. Use the tool `jtagconfig` to determine the index."},
                        {'name' : 'pnr',
                         'type' : 'String',
                         'desc' : 'P&R tool. Allowed values are quartus (default), dse (to perform a DSE based seed sweep) and none (to just run synthesis)'},
                        {'name' : 'explore',
                         'type' : 'String',
                         'desc' : 'DSE exploration type, defaults to "seed" for a seed sweep'},
                        {'name' : 'launcher',
                         'type' : 'String',
                         'desc' : 'DSE launcher, defaults to "local" for local building'},
                        {'name' : 'processors',
                         'type' : 'String',
                         'desc' : 'The maximum number of parallel processors to use for DSE jobs, defaults to 0 for unlimited'},
                        {'name' : 'timeout',
                         'type' : 'String',
                         'desc' : 'Time limit for DSE runs, defaults to "24h0m" for one day'},
                        {'name' : 'stop_on_success',
                         'type' : 'String',
                         'desc' : 'True (default) to stop after the first DSE result has met all timing requirements, False to always build all seeds'},
                        {'name' : 'parallelism',
                         'type' : 'String',
                         'desc' : 'Maximum number of P&R jobs DSE may run at once, default is 4'},
                        {'name' : 'seeds',
                         'type' : 'String',
                         'desc' : 'Comma seperated list of seeds for DSE to try, default is "1,2,3,4"'}],
                    'lists' : [
                        {'name' : 'quartus_options',
                         'type' : 'String',
                         'desc' : 'Additional options for Quartus'},
                        ]}
    """ Initial setup of the class

    This calls the parent constructor, but also identifies whether
    the current system is using a Standard or Pro edition of Quartus.
    """
    def __init__(self, edam=None, work_root=None, eda_api=None):
        if not edam:
            edam = eda_api

        super(Quartus, self).__init__(edam, work_root)

        # Acquire quartus_sh identification information from available tool if
        # possible. We always default to version 18.1 Standard if a problem is encountered
        version = {
            'major':   '18',
            'minor':   '1',
            'patch':   '0',
            'date':    '01/01/2019',
            'edition': 'Standard'
        }
        try:
            qsh_text = subprocess.Popen(["quartus_sh", "--version"], stdout=subprocess.PIPE, env=os.environ).communicate()[0]

            # Attempt to pattern match the output. Examples include
            # Version 16.1.2 Build 203 01/18/2017 SJ Standard Edition
            # Version 17.1.2 Build 304 01/31/2018 SJ Pro Edition
            version_exp = r'Version (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+) ' + \
                          r'Build (?P<build>\d+) (?P<date>\d{2}/\d{2}/\d{4}) SJ '    + \
                          r'(?P<edition>(Lite|Standard|Pro)) Edition'

            match = re.search(version_exp, str(qsh_text))
            if match != None:
                version = match.groupdict()
        except:
            # It is possible for this to have been run on a box without
            # Quartus being installed. Allow these errors to be ignored
            logger.warning("Unable to recognise Quartus version via quartus_sh")

        self.isPro = (version['edition'] == "Pro")

        # Quartus Pro 17 and later use 1/0 for boolean generics. Other editions
        # and versions use "true"/"false" strings
        if (version['edition'] != "Pro") or (int(version['major']) < 17):
            self.jinja_env.filters['generic_value_str'] = \
                partial(self.jinja_env.filters['generic_value_str'], bool_is_str=True)<commit_msg>Less restrictive regex for determining the version of Quartus.<commit_after>import logging
import os.path
import os
import platform
import subprocess
import re
import xml.etree.ElementTree as ET
from functools import partial
from edalize.edatool import Edatool

logger = logging.getLogger(__name__)

class Quartus(Edatool):

    argtypes = ['vlogdefine', 'vlogparam', 'generic']

    # Define Standard edition to be our default version
    isPro = False
    makefile_template = {False : "quartus-std-makefile.j2",
                         True  : "quartus-pro-makefile.j2"}
    dse_template = 'quartus-dse.j2'

    @classmethod
    def get_doc(cls, api_ver):
        if api_ver == 0:
            return {'description' : "The Quartus backend supports Intel Quartus Std and Pro editions to build systems and program the FPGA",
                    'members' : [
                        {'name' : 'family',
                         'type' : 'String',
                         'desc' : 'FPGA family (e.g. Cyclone V)'},
                        {'name' : 'device',
                         'type' : 'String',
                         'desc' : 'FPGA device (e.g. 5CSXFC6D6F31C8ES)'},
                        {'name' : 'cable',
                         'type' : 'String',
                         'desc' : "Specifies the FPGA's JTAG programming cable. Use the tool `jtagconfig` to determine the available cables."},
                        {'name' : 'board_device_index',
                         'type' : 'String',
                         'desc' : "Specifies the FPGA's device number in the JTAG chain. The device index specifies the device where the flash programmer looks for the Nios® II JTAG debug module. JTAG devices are numbered relative to the JTAG chain, starting at 1. Use the tool `jtagconfig` to determine the index."},
                        {'name' : 'pnr',
                         'type' : 'String',
                         'desc' : 'P&R tool. Allowed values are quartus (default), dse (to perform a DSE based seed sweep) and none (to just run synthesis)'},
                        {'name' : 'explore',
                         'type' : 'String',
                         'desc' : 'DSE exploration type, defaults to "seed" for a seed sweep'},
                        {'name' : 'launcher',
                         'type' : 'String',
                         'desc' : 'DSE launcher, defaults to "local" for local building'},
                        {'name' : 'processors',
                         'type' : 'String',
                         'desc' : 'The maximum number of parallel processors to use for DSE jobs, defaults to 0 for unlimited'},
                        {'name' : 'timeout',
                         'type' : 'String',
                         'desc' : 'Time limit for DSE runs, defaults to "24h0m" for one day'},
                        {'name' : 'stop_on_success',
                         'type' : 'String',
                         'desc' : 'True (default) to stop after the first DSE result has met all timing requirements, False to always build all seeds'},
                        {'name' : 'parallelism',
                         'type' : 'String',
                         'desc' : 'Maximum number of P&R jobs DSE may run at once, default is 4'},
                        {'name' : 'seeds',
                         'type' : 'String',
                         'desc' : 'Comma seperated list of seeds for DSE to try, default is "1,2,3,4"'}],
                    'lists' : [
                        {'name' : 'quartus_options',
                         'type' : 'String',
                         'desc' : 'Additional options for Quartus'},
                        ]}
    """ Initial setup of the class

    This calls the parent constructor, but also identifies whether
    the current system is using a Standard or Pro edition of Quartus.
    """
    def __init__(self, edam=None, work_root=None, eda_api=None):
        if not edam:
            edam = eda_api

        super(Quartus, self).__init__(edam, work_root)

        # Acquire quartus_sh identification information from available tool if
        # possible. We always default to version 18.1 Standard if a problem is encountered
        version = {
            'major':   '18',
            'minor':   '1',
            'patch':   '0',
            'date':    '01/01/2019',
            'edition': 'Standard'
        }
        try:
            qsh_text = subprocess.Popen(["quartus_sh", "--version"], stdout=subprocess.PIPE, env=os.environ).communicate()[0]

            # Attempt to pattern match the output. Examples include
            # Version 16.1.2 Build 203 01/18/2017 SJ Standard Edition
            # Version 17.1.2 Build 304 01/31/2018 SJ Pro Edition
            version_exp = r'Version (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+) ' + \
                          r'Build (?P<build>\d+) (?P<date>\d{2}/\d{2}/\d{4}) (?:\w+) '    + \
                          r'(?P<edition>(Lite|Standard|Pro)) Edition'

            match = re.search(version_exp, str(qsh_text))
            if match != None:
                version = match.groupdict()
        except:
            # It is possible for this to have been run on a box without
            # Quartus being installed. Allow these errors to be ignored
            logger.warning("Unable to recognise Quartus version via quartus_sh")

        self.isPro = (version['edition'] == "Pro")

        # Quartus Pro 17 and later use 1/0 for boolean generics. Other editions
        # and versions use "true"/"false" strings
        if (version['edition'] != "Pro") or (int(version['major']) < 17):
            self.jinja_env.filters['generic_value_str'] = \
                partial(self.jinja_env.filters['generic_value_str'], bool_is_str=True)
{'fraction_non_alphanumeric': 0.11133321745176429, 'fraction_numerical': 0.013036676516600034, 'mean_word_length': 1.6193944912360574, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 2}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5172291', 'n_tokens_mistral': 3264, 'n_tokens_neox': 2989, 'n_words': 1017}