Coverage for tsfpga/vivado/common.py: 70%
50 statements
« prev ^ index » next coverage.py v7.6.12, created at 2025-02-21 20:51 +0000
« prev ^ index » next coverage.py v7.6.12, created at 2025-02-21 20:51 +0000
1# --------------------------------------------------------------------------------------------------
2# Copyright (c) Lukas Vik. All rights reserved.
3#
4# This file is part of the tsfpga project, a project platform for modern FPGA development.
5# https://tsfpga.com
6# https://github.com/tsfpga/tsfpga
7# --------------------------------------------------------------------------------------------------
9from __future__ import annotations
11from pathlib import Path
12from shutil import which
14from vunit.ostools import Process
16from tsfpga.git_utils import get_git_sha
17from tsfpga.math_utils import to_binary_string
20def run_vivado_tcl(vivado_path: Path | None, tcl_file: Path, no_log_file: bool = False) -> bool:
21 """
22 Setting cwd ensures that any .log or .jou files produced are placed in
23 the same directory as the TCL file that produced them.
25 Arguments:
26 vivado_path: Path to Vivado executable. Can set to ``None``
27 to use whatever version is in ``PATH``.
28 tcl_file: Path to TCL file.
29 no_log_file: Optionally set Vivado flags to not create log and journal files.
31 Return:
32 True if everything went well.
33 """
34 tcl_file = tcl_file.resolve()
36 cmd = [
37 str(get_vivado_path(vivado_path)),
38 "-mode",
39 "batch",
40 "-notrace",
41 "-source",
42 str(tcl_file),
43 ]
44 if no_log_file:
45 cmd += ["-nojournal", "-nolog"]
47 try:
48 Process(args=cmd, cwd=tcl_file.parent).consume_output()
49 except Process.NonZeroExitCode:
50 return False
51 return True
54def run_vivado_gui(vivado_path: Path | None, project_file: Path) -> bool:
55 """
56 Setting cwd ensures that any .log or .jou files produced are placed in
57 the same directory as the project.
59 Arguments:
60 vivado_path: Path to Vivado executable.
61 Leave as ``None`` to use whatever is available in the system ``PATH``.
62 project_file: Path to a project .xpr file.
64 Return:
65 True if everything went well.
66 """
67 project_file = project_file.resolve()
68 if not project_file.exists():
69 raise FileNotFoundError(f"Project does not exist: {project_file}")
71 cmd = [str(get_vivado_path(vivado_path)), "-mode", "gui", str(project_file)]
73 try:
74 Process(args=cmd, cwd=project_file.parent).consume_output()
75 except Process.NonZeroExitCode:
76 return False
77 return True
80def get_vivado_path(vivado_path: Path | None = None) -> Path:
81 """
82 Wrapper to get a path to Vivado executable.
84 Arguments:
85 vivado_path: Path to vivado executable.
86 Leave as ``None`` to use whatever is available in the system ``PATH``.
87 """
88 if vivado_path is not None:
89 return vivado_path.resolve()
91 which_vivado = which("vivado")
92 if which_vivado is None:
93 raise FileNotFoundError("Could not find vivado on PATH")
95 return Path(which_vivado).resolve()
98def get_vivado_version(vivado_path: Path | None = None) -> str:
99 """
100 Get the version number of the Vivado installation.
102 Arguments:
103 vivado_path: Path to vivado executable.
104 Leave as ``None`` to use whatever is available in the system ``PATH``.
106 Return:
107 The version, e.g. ``"2021.2"``.
108 """
109 vivado_path = get_vivado_path(vivado_path=vivado_path)
111 # E.g. "/home/lukas/work/Xilinx/Vivado/2021.2/bin/vivado" -> "2021.2"
112 return vivado_path.parent.parent.name
115def get_git_sha_slv(git_directory: Path) -> tuple[str, str]:
116 """
117 Get the current git SHA encoded as 32-character binary strings. Suitable for setting
118 as ``std_logic_vector`` generics to a Vivado build, where they can be assigned to
119 software-accessible registers to keep track of what revision an FPGA was built from.
121 Will return the left-most 16 characters of the git SHA, encoded into two 32-character
122 binary strings.
124 Arguments:
125 git_directory: The directory where git commands will be run.
127 Return:
128 First object in tuple is the left-most eight characters of the git SHA
129 encoded as a 32-character binary string.
130 Second object is the next eight characters from the git SHA.
131 """
132 git_sha = get_git_sha(directory=git_directory)
133 if len(git_sha) != 16:
134 raise ValueError("Wrong string length")
136 def hex_to_binary_string(hex_string: str) -> str:
137 if len(hex_string) != 8:
138 raise ValueError("Wrong string length")
139 int_value = int(hex_string, base=16)
141 return to_binary_string(value=int_value, result_width=32)
143 left_binary_string = hex_to_binary_string(hex_string=git_sha[0:8])
144 right_binary_string = hex_to_binary_string(hex_string=git_sha[8:16])
146 return (left_binary_string, right_binary_string)
149def to_tcl_path(path: Path) -> str:
150 """
151 Return a path string in a format suitable for TCL.
152 """
153 return str(path.resolve()).replace("\\", "/")