Coverage for tsfpga/vivado/common.py: 73%

48 statements  

« prev     ^ index     » next       coverage.py v6.4.4, created at 2022-09-29 20:01 +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://gitlab.com/tsfpga/tsfpga 

7# -------------------------------------------------------------------------------------------------- 

8 

9from pathlib import Path 

10from shutil import which 

11 

12from vunit.ostools import Process 

13 

14from tsfpga.git_utils import get_git_sha 

15from tsfpga.math_utils import to_binary_string 

16 

17 

18def run_vivado_tcl(vivado_path, tcl_file, no_log_file=False): 

19 """ 

20 Setting cwd ensures that any .log or .jou files produced are placed in 

21 the same directory as the TCL file that produced them. 

22 

23 Arguments: 

24 vivado_path (pathlib.Path): Path to Vivado executable. Can set to ``None`` 

25 to use whatever version is in ``PATH``. 

26 tcl_file (pathlib.Path): Path to TCL file. 

27 

28 Return: 

29 bool: True if everything went well. 

30 """ 

31 tcl_file = tcl_file.resolve() 

32 

33 cmd = [ 

34 str(get_vivado_path(vivado_path)), 

35 "-mode", 

36 "batch", 

37 "-notrace", 

38 "-source", 

39 str(tcl_file), 

40 ] 

41 if no_log_file: 

42 cmd += ["-nojournal", "-nolog"] 

43 

44 try: 

45 Process(args=cmd, cwd=tcl_file.parent).consume_output() 

46 except Process.NonZeroExitCode: 

47 return False 

48 return True 

49 

50 

51def run_vivado_gui(vivado_path, project_file): 

52 """ 

53 Setting cwd ensures that any .log or .jou files produced are placed in 

54 the same directory as the project. 

55 

56 Arguments: 

57 vivado_path (pathlib.Path): Path to Vivado executable. Can set to ``None`` 

58 to use whatever version is in ``PATH``. 

59 project_file (pathlib.Path): Path to a project .xpr file. 

60 

61 Return: 

62 bool: True if everything went well. 

63 """ 

64 project_file = project_file.resolve() 

65 if not project_file.exists(): 

66 raise FileNotFoundError(f"Project does not exist: {project_file}") 

67 

68 cmd = [str(get_vivado_path(vivado_path)), "-mode", "gui", str(project_file)] 

69 

70 try: 

71 Process(args=cmd, cwd=project_file.parent).consume_output() 

72 except Process.NonZeroExitCode: 

73 return False 

74 return True 

75 

76 

77def get_vivado_path(vivado_path=None): 

78 """ 

79 Wrapper to get a path to Vivado executable. 

80 

81 Arguments: 

82 vivado_path (pathlib.Path): Path to vivado executable. Set to ``None`` to use whatever 

83 is available in the system ``PATH``. 

84 

85 Returns: 

86 pathlib.Path: The path. 

87 """ 

88 if vivado_path is not None: 

89 return vivado_path.resolve() 

90 

91 which_vivado = which("vivado") 

92 if which_vivado is None: 

93 raise FileNotFoundError("Could not find vivado on PATH") 

94 

95 return Path(which_vivado).resolve() 

96 

97 

98def get_vivado_version(vivado_path=None): 

99 """ 

100 Get the version number of the Vivado installation. 

101 

102 Arguments: 

103 vivado_path (pathlib.Path): Path to vivado executable. Set to ``None`` to use whatever 

104 is available in the system ``PATH``. 

105 

106 Returns: 

107 str: The version, e.g. ``"2021.2"``. 

108 """ 

109 vivado_path = get_vivado_path(vivado_path=vivado_path) 

110 

111 # E.g. "/home/lukas/work/Xilinx/Vivado/2021.2/bin/vivado" -> "2021.2" 

112 vivado_version = vivado_path.parent.parent.name 

113 

114 return vivado_version 

115 

116 

117def get_git_sha_slv(git_directory): 

118 """ 

119 Get the current git SHA encoded as 32-character binary strings. Suitable for setting 

120 as ``std_logic_vector`` generics to a Vivado build, where they can be assigned to 

121 software-accessible registers to keep track of what revision an FPGA was built from. 

122 

123 Will return the left-most 16 characters of the git SHA, encoded into two 32-character strings. 

124 

125 Arguments: 

126 directory (pathlib.Path): The directory where git commands will be run. 

127 

128 Returns: 

129 tuple(str, str): First object in tuple is the left-most eight characters of the git SHA 

130 encoded as a 32-character binary string. Second object is the next eight characters from 

131 the git SHA. 

132 """ 

133 git_sha = get_git_sha(directory=git_directory) 

134 assert len(git_sha) == 16 

135 

136 def hex_to_binary_string(hex_string): 

137 assert len(hex_string) == 8 

138 int_value = int(hex_string, base=16) 

139 

140 return to_binary_string(int_value=int_value, result_width=32) 

141 

142 left_binary_string = hex_to_binary_string(hex_string=git_sha[0:8]) 

143 right_binary_string = hex_to_binary_string(hex_string=git_sha[8:16]) 

144 

145 return (left_binary_string, right_binary_string) 

146 

147 

148def to_tcl_path(path): 

149 """ 

150 Return a path string in a format suitable for TCL. 

151 """ 

152 return str(path.resolve()).replace("\\", "/")