Ejemplo n.º 1
0
 def preprocess(self, code, file_name="fn.v", include_paths=None):
     """
     Tokenize & Preprocess
     """
     tokenizer = VerilogTokenizer()
     preprocessor = VerilogPreprocessor(tokenizer)
     write_file(file_name, code)
     tokens = tokenizer.tokenize(code, file_name=file_name)
     defines = {}
     included_files = []
     with mock.patch("vunit.parsing.verilog.preprocess.LOGGER", autospec=True) as logger:
         tokens = preprocessor.preprocess(tokens, defines, include_paths, included_files)
     return PreprocessResult(self, tokens, defines,
                             [file_name for _, file_name in included_files if file_name is not None],
                             logger)
Ejemplo n.º 2
0
Archivo: parser.py Proyecto: wzab/vunit
 def __init__(self, database=None):
     self._tokenizer = VerilogTokenizer()
     self._preprocessor = VerilogPreprocessor(self._tokenizer)
     self._database = database
     self._content_cache = {}
Ejemplo n.º 3
0
Archivo: parser.py Proyecto: wzab/vunit
class VerilogParser(object):
    """
    Parse a single Verilog file
    """
    def __init__(self, database=None):
        self._tokenizer = VerilogTokenizer()
        self._preprocessor = VerilogPreprocessor(self._tokenizer)
        self._database = database
        self._content_cache = {}

    def parse(self, file_name, include_paths=None, defines=None):
        """
        Parse verilog code
        """

        defines = {} if defines is None else defines
        include_paths = [] if include_paths is None else include_paths
        include_paths = [dirname(file_name)] + include_paths

        cached = self._lookup_parse_cache(file_name, include_paths, defines)
        if cached is not None:
            return cached

        initial_defines = dict(
            (key, Macro(key, self._tokenizer.tokenize(value)))
            for key, value in defines.items())
        code = read_file(file_name, encoding=HDL_FILE_ENCODING)
        tokens = self._tokenizer.tokenize(code, file_name=file_name)
        included_files = []
        pp_tokens = self._preprocessor.preprocess(
            tokens,
            include_paths=include_paths,
            defines=initial_defines,
            included_files=included_files)

        included_files_for_design_file = [
            name for _, name in included_files if name is not None
        ]
        result = VerilogDesignFile.parse(pp_tokens,
                                         included_files_for_design_file)

        if self._database is None:
            return result

        self._store_result(file_name, result, included_files, defines)
        return result

    @staticmethod
    def _key(file_name):
        """
        Returns the database key for parse results of file_name
        """
        return ("CachedVerilogParser.parse(%s)" % abspath(file_name)).encode()

    def _store_result(self, file_name, result, included_files, defines):
        """
        Store parse result into back into cache
        """
        new_included_files = [(short_name, full_name,
                               self._content_hash(full_name))
                              for short_name, full_name in included_files]
        key = self._key(file_name)
        self._database[key] = self._content_hash(
            file_name), new_included_files, defines, result
        return result

    def _content_hash(self, file_name):
        """
        Hash the contents of the file
        """
        if file_name is None or not exists(file_name):
            return None
        if file_name not in self._content_cache:
            self._content_cache[file_name] = file_content_hash(
                file_name, encoding=HDL_FILE_ENCODING, database=self._database)
        return self._content_cache[file_name]

    def _lookup_parse_cache(self, file_name, include_paths, defines):
        """
        Use verilog code from cache
        """
        # pylint: disable=too-many-return-statements

        if self._database is None:
            return None

        key = self._key(file_name)
        if key not in self._database:
            return None

        old_content_hash, old_included_files, old_defines, old_result = self._database[
            key]
        if old_defines != defines:
            return None

        if old_content_hash != self._content_hash(file_name):
            return None

        for include_str, included_file_name, last_content_hash in old_included_files:
            if last_content_hash != self._content_hash(included_file_name):
                return None

            if find_included_file(include_paths,
                                  include_str) != included_file_name:
                return None

        LOGGER.debug("Re-using cached Verilog parse results for %s", file_name)

        return old_result
Ejemplo n.º 4
0
 def __init__(self, database=None):
     self._tokenizer = VerilogTokenizer()
     self._preprocessor = VerilogPreprocessor(self._tokenizer)
     self._database = database
     self._content_cache = {}
Ejemplo n.º 5
0
class VerilogParser(object):
    """
    Parse a single Verilog file
    """

    def __init__(self, database=None):
        self._tokenizer = VerilogTokenizer()
        self._preprocessor = VerilogPreprocessor(self._tokenizer)
        self._database = database
        self._content_cache = {}

    def parse(self, file_name, include_paths=None, defines=None):
        """
        Parse verilog code
        """

        defines = {} if defines is None else defines
        include_paths = [] if include_paths is None else include_paths
        include_paths = [dirname(file_name)] + include_paths

        cached = self._lookup_parse_cache(file_name, include_paths, defines)
        if cached is not None:
            return cached

        initial_defines = dict((key, Macro(key, self._tokenizer.tokenize(value)))
                               for key, value in defines.items())
        code = read_file(file_name, encoding=HDL_FILE_ENCODING)
        tokens = self._tokenizer.tokenize(code, file_name=file_name)
        included_files = []
        pp_tokens = self._preprocessor.preprocess(tokens,
                                                  include_paths=include_paths,
                                                  defines=initial_defines,
                                                  included_files=included_files)

        included_files_for_design_file = [name for _, name in included_files if name is not None]
        result = VerilogDesignFile.parse(pp_tokens, included_files_for_design_file)

        if self._database is None:
            return result

        self._store_result(file_name, result, included_files, defines)
        return result

    @staticmethod
    def _key(file_name):
        """
        Returns the database key for parse results of file_name
        """
        return ("CachedVerilogParser.parse(%s)" % abspath(file_name)).encode()

    def _store_result(self, file_name, result, included_files, defines):
        """
        Store parse result into back into cache
        """
        new_included_files = [(short_name, full_name, self._content_hash(full_name))
                              for short_name, full_name in included_files]
        key = self._key(file_name)
        self._database[key] = self._content_hash(file_name), new_included_files, defines, result
        return result

    def _content_hash(self, file_name):
        """
        Hash the contents of the file
        """
        if file_name is None or not exists(file_name):
            return None
        if file_name not in self._content_cache:
            self._content_cache[file_name] = file_content_hash(file_name,
                                                               encoding=HDL_FILE_ENCODING,
                                                               database=self._database)
        return self._content_cache[file_name]

    def _lookup_parse_cache(self, file_name, include_paths, defines):
        """
        Use verilog code from cache
        """
        # pylint: disable=too-many-return-statements

        if self._database is None:
            return None

        key = self._key(file_name)
        if key not in self._database:
            return None

        old_content_hash, old_included_files, old_defines, old_result = self._database[key]
        if old_defines != defines:
            return None

        if old_content_hash != self._content_hash(file_name):
            return None

        for include_str, included_file_name, last_content_hash in old_included_files:
            if last_content_hash != self._content_hash(included_file_name):
                return None

            if find_included_file(include_paths, include_str) != included_file_name:
                return None

        LOGGER.debug("Re-using cached Verilog parse results for %s", file_name)

        return old_result