예제 #1
0
 def _getFlags(self, path, scope):
     # type: (Path, BuildFlagScope) -> BuildFlags
     """
     Gets flags to build the path, both builder based and from the database.
     If a build is forced, assume we're building a single file (not its
     dependencies)
     """
     return tuple(self._database.getFlags(path, scope)) + tuple(
         self.default_flags.get(scope, {}).get(FileType.fromPath(path),
                                               ()) + self.default_flags.
         get(BuildFlagScope.all, {}).get(FileType.fromPath(path), ()))
예제 #2
0
    def addSource(self, path, library, single_flags=None, dependencies_flags=None):
        # type: (Path, Optional[str], Optional[BuildFlags], Optional[BuildFlags]) -> None
        """
        Adds a source to the database, triggering its parsing even if the
        source has already been added previously
        """
        _logger.info(
            "Adding %s, library=%s, flags=(single=%s, dependencies=%s)",
            path,
            library,
            single_flags,
            dependencies_flags,
        )
        self._paths.add(path)
        self._flags_map[path] = {
            BuildFlagScope.single: tuple(single_flags or ()),
            BuildFlagScope.dependencies: tuple(dependencies_flags or ()),
        }
        if library is not None:
            self._library_map[path] = Identifier(
                library, case_sensitive=FileType.fromPath(path) != FileType.vhdl
            )

        # TODO: Parse on a process pool
        self._parseSource(path)
예제 #3
0
def getSourceParserFromPath(
        path):  # type: (Path) -> Union[VhdlParser, VerilogParser]
    """
    Returns either a VhdlParser or VerilogParser based on the path's file
    extension
    """
    return PARSERS[FileType.fromPath(path)](path)
예제 #4
0
 def __init__(self, filename):
     # type: (Path, ) -> None
     assert isinstance(filename, Path), "Invalid type: {}".format(filename)
     self.filename = filename
     self._cache = {}  # type: Dict[str, Any]
     self._content = None  # type: Optional[str]
     self._mtime = 0  # type: Optional[float]
     self.filetype = FileType.fromPath(self.filename)
     self._dependencies = None  # type: Optional[Set[BaseDependencySpec]]
     self._design_units = None  # type: Optional[Set[tAnyDesignUnit]]
     self._libraries = None
예제 #5
0
    def _buildSource(self, path, library, flags=None):
        # type: (Path, Identifier, Optional[BuildFlags]) -> Iterable[str]
        filetype = FileType.fromPath(path)
        if filetype == FileType.vhdl:
            return self._buildVhdl(path, library, flags)
        if filetype in (FileType.verilog, FileType.systemverilog):
            return self._buildVerilog(path, library, flags)

        self._logger.error(  # pragma: no cover
            "Unknown file type %s for path '%s'", filetype, path)

        return ""  # Just to satisfy pylint
예제 #6
0
    def build(self, path, library, scope, forced=False):
        # type: (Path, Identifier, BuildFlagScope, bool) -> Tuple[Set[CheckerDiagnostic], Set[RebuildInfo]]
        """
        Method that interfaces with parents and implements the building
        chain
        """

        if not self._isFileTypeSupported(path):
            self._logger.warning(
                "Path '%s' with file type '%s' is not "
                "supported",
                path,
                FileType.fromPath(path),
            )
            return set(), set()

        if path not in self._build_info_cache:
            self._build_info_cache[path] = {
                "compile_time": 0.0,
                "diagnostics": [],
                "rebuilds": [],
            }

        cached_info = self._build_info_cache[path]

        build = False
        if forced:
            build = True
            self._logger.info("Forcing build of %s", str(path))
        elif path.mtime > cached_info["compile_time"]:
            build = True
            self._logger.info("Building %s", str(path))

        if build:
            with self._lock:
                diagnostics, rebuilds = self._buildAndGetDiagnostics(
                    path, library, self._getFlags(path, scope))

            cached_info["diagnostics"] = diagnostics
            cached_info["rebuilds"] = rebuilds
            cached_info["compile_time"] = path.mtime

            if DiagType.ERROR in [x.severity for x in diagnostics]:
                cached_info["compile_time"] = 0

        else:
            self._logger.debug("Nothing to do for %s", path)
            diagnostics = cached_info["diagnostics"]
            rebuilds = cached_info["rebuilds"]

        return diagnostics, rebuilds
예제 #7
0
def findRtlSourcesByPath(path):
    # type: (Path) -> Iterable[Path]
    """
    Finds RTL sources (files with extensions within FileType enum) inside
    <path>
    """
    for dirpath, _, filenames in os.walk(path.name):
        for filename in filenames:
            full_path = Path(p.join(dirpath, filename))

            if not p.isfile(full_path.name):
                continue

            try:
                # FileType.fromPath will fail if the file's extension is not
                # valid (one of '.vhd', '.vhdl', '.v', '.vh', '.sv',
                # '.svh')
                FileType.fromPath(full_path)
            except UnknownTypeExtension:
                continue

            if isFileReadable(full_path.name):
                yield full_path
예제 #8
0
def _expand(config, ref_path):
    # type: (Dict[str, Any], str) -> Iterable[SourceEntry]
    """
    Expands the sources defined in the config dict into a list of tuples
    """

    flags = {}

    for filetype in FileType:
        filetype_cfg = config.pop(filetype.value, {}).pop("flags", {})
        flags[filetype] = (
            filetype_cfg.get(BuildFlagScope.single.value, ()),
            filetype_cfg.get(BuildFlagScope.dependencies.value, ()),
            filetype_cfg.get(BuildFlagScope.all.value, ()),
        )

    sources = config.pop("sources", None)

    # If no sources were defined, search ref_path
    if sources is None:
        _logger.debug("No sources found, will search %s", ref_path)
        sources = (x.name for x in findRtlSourcesByPath(Path(ref_path)))

    for entry in sources:
        source = JsonSourceEntry.make(entry)
        path_expr = (
            source.path_expr
            if p.isabs(source.path_expr)
            else p.join(ref_path, source.path_expr)
        )

        for _path in glob(path_expr):
            path = Path(_path, ref_path)

            try:
                filetype = FileType.fromPath(path)
            except UnknownTypeExtension:
                _logger.warning("Won't include non RTL file '%s'", path)
                continue

            single_flags = flags[filetype][0]
            dependencies_flags = flags[filetype][1]
            global_flags = flags[filetype][2]

            yield SourceEntry(
                path,
                source.library,
                tuple(global_flags) + tuple(single_flags) + tuple(source.flags),
                tuple(global_flags) + tuple(dependencies_flags),
            )
예제 #9
0
    def _getExtraFlags(self, path):
        # type: (Path) -> Iterable[str]
        """
        Gets extra flags configured for the specific language
        """
        self._logger.debug("Getting flags for %s", path)
        lang = FileType.fromPath(path)
        if lang is FileType.systemverilog:
            lang = FileType.verilog

        libs = []  # type: List[str]
        for library in self._added_libraries | self._external_libraries[lang]:
            libs = ["-L", library.name]
        for incdir in self._getIncludesForPath(path):
            libs += ["+incdir+" + incdir]
        return libs
예제 #10
0
    def __init__(
            self,
            design_units,  # type: Iterable[Dict[str, str]]
            library=None,  # type: str
            dependencies=None,  # type: Iterable[MockDep]
            filename=None,  # type: Optional[str]
    ):

        self._design_units = list(design_units or [])

        if filename is not None:
            self._filename = Path(p.join(self.base_path, filename))
        else:
            library = "lib_not_set" if library is None else library
            self._filename = Path(
                p.join(
                    self.base_path,
                    library,
                    "_{}.vhd".format(self._design_units[0]["name"]),
                ))

        self.filetype = FileType.fromPath(self.filename)
        #  self.abspath = p.abspath(self.filename)
        self.flags = []  # type: ignore

        self.library = library
        self._dependencies = []  # type: List[RequiredDesignUnit]
        for dep_spec in dependencies or []:
            _name = dep_spec[0]
            _library = "work"

            try:
                _library, _name = dep_spec  # type: ignore
            except ValueError:
                pass

            self._dependencies.append(
                RequiredDesignUnit(
                    self._filename,
                    Identifier(_name, False),
                    Identifier(_library, False),
                ))

        self._createMockFile()
예제 #11
0
    def _buildVerilog(self, path, library, flags=None):
        # type: (Path, Identifier, Optional[BuildFlags]) -> Iterable[str]
        "Builds a Verilog/SystemVerilog file"
        cmd = [
            "vlog",
            "-modelsimini",
            self._modelsim_ini.name,
            "-quiet",
            "-work",
            p.join(self._work_folder, library.name),
        ]

        if FileType.fromPath(path) == FileType.systemverilog:
            cmd += ["-sv"]
        if flags:  # pragma: no cover
            cmd += flags

        cmd += self._getExtraFlags(path)
        cmd += [path.name]

        return runShellCommand(cmd)
예제 #12
0
 def _isFileTypeSupported(self, path):
     # type: (Path) -> bool
     """
     Checks if a given path is supported by this builder
     """
     return FileType.fromPath(path) in self.file_types