Coverage for tsfpga/vivado/common.py: 73%
49 statements
« prev ^ index » next coverage.py v7.6.9, created at 2024-12-20 20:52 +0000
« prev ^ index » next coverage.py v7.6.9, created at 2024-12-20 20:52 +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# --------------------------------------------------------------------------------------------------
9# Standard libraries
10from pathlib import Path
11from shutil import which
12from typing import Optional
14# Third party libraries
15from vunit.ostools import Process
17# First party libraries
18from tsfpga.git_utils import get_git_sha
19from tsfpga.math_utils import to_binary_string
22def run_vivado_tcl(vivado_path: Optional[Path], tcl_file: Path, no_log_file: bool = False) -> bool:
23 """
24 Setting cwd ensures that any .log or .jou files produced are placed in
25 the same directory as the TCL file that produced them.
27 Arguments:
28 vivado_path: Path to Vivado executable. Can set to ``None``
29 to use whatever version is in ``PATH``.
30 tcl_file: Path to TCL file.
31 no_log_file: Optionally set Vivado flags to not create log and journal files.
33 Return:
34 True if everything went well.
35 """
36 tcl_file = tcl_file.resolve()
38 cmd = [
39 str(get_vivado_path(vivado_path)),
40 "-mode",
41 "batch",
42 "-notrace",
43 "-source",
44 str(tcl_file),
45 ]
46 if no_log_file:
47 cmd += ["-nojournal", "-nolog"]
49 try:
50 Process(args=cmd, cwd=tcl_file.parent).consume_output()
51 except Process.NonZeroExitCode:
52 return False
53 return True
56def run_vivado_gui(vivado_path: Optional[Path], project_file: Path) -> bool:
57 """
58 Setting cwd ensures that any .log or .jou files produced are placed in
59 the same directory as the project.
61 Arguments:
62 vivado_path: Path to Vivado executable.
63 Leave as ``None`` to use whatever is available in the system ``PATH``.
64 project_file: Path to a project .xpr file.
66 Return:
67 True if everything went well.
68 """
69 project_file = project_file.resolve()
70 if not project_file.exists():
71 raise FileNotFoundError(f"Project does not exist: {project_file}")
73 cmd = [str(get_vivado_path(vivado_path)), "-mode", "gui", str(project_file)]
75 try:
76 Process(args=cmd, cwd=project_file.parent).consume_output()
77 except Process.NonZeroExitCode:
78 return False
79 return True
82def get_vivado_path(vivado_path: Optional[Path] = None) -> Path:
83 """
84 Wrapper to get a path to Vivado executable.
86 Arguments:
87 vivado_path: Path to vivado executable.
88 Leave as ``None`` to use whatever is available in the system ``PATH``.
89 """
90 if vivado_path is not None:
91 return vivado_path.resolve()
93 which_vivado = which("vivado")
94 if which_vivado is None:
95 raise FileNotFoundError("Could not find vivado on PATH")
97 return Path(which_vivado).resolve()
100def get_vivado_version(vivado_path: Optional[Path] = None) -> str:
101 """
102 Get the version number of the Vivado installation.
104 Arguments:
105 vivado_path: Path to vivado executable.
106 Leave as ``None`` to use whatever is available in the system ``PATH``.
108 Return:
109 The version, e.g. ``"2021.2"``.
110 """
111 vivado_path = get_vivado_path(vivado_path=vivado_path)
113 # E.g. "/home/lukas/work/Xilinx/Vivado/2021.2/bin/vivado" -> "2021.2"
114 vivado_version = vivado_path.parent.parent.name
116 return vivado_version
119def get_git_sha_slv(git_directory: Path) -> tuple[str, str]:
120 """
121 Get the current git SHA encoded as 32-character binary strings. Suitable for setting
122 as ``std_logic_vector`` generics to a Vivado build, where they can be assigned to
123 software-accessible registers to keep track of what revision an FPGA was built from.
125 Will return the left-most 16 characters of the git SHA, encoded into two 32-character
126 binary strings.
128 Arguments:
129 directory: The directory where git commands will be run.
131 Return:
132 First object in tuple is the left-most eight characters of the git SHA
133 encoded as a 32-character binary string.
134 Second object is the next eight characters from the git SHA.
135 """
136 git_sha = get_git_sha(directory=git_directory)
137 assert len(git_sha) == 16
139 def hex_to_binary_string(hex_string: str) -> str:
140 assert len(hex_string) == 8
141 int_value = int(hex_string, base=16)
143 return to_binary_string(value=int_value, result_width=32)
145 left_binary_string = hex_to_binary_string(hex_string=git_sha[0:8])
146 right_binary_string = hex_to_binary_string(hex_string=git_sha[8:16])
148 return (left_binary_string, right_binary_string)
151def to_tcl_path(path: Path) -> str:
152 """
153 Return a path string in a format suitable for TCL.
154 """
155 return str(path.resolve()).replace("\\", "/")