Coverage for tsfpga/vivado/simlib_common.py: 85%

61 statements  

« prev     ^ index     » next       coverage.py v6.4, created at 2022-05-28 04:01 +0000

1# -------------------------------------------------------------------------------------------------- 

2# Copyright (c) Lukas Vik. All rights reserved. 

3# 

4# This file is part of the tsfpga project. 

5# https://tsfpga.com 

6# https://gitlab.com/tsfpga/tsfpga 

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

8 

9import platform 

10from shutil import make_archive 

11import zipfile 

12 

13from tsfpga.system_utils import create_file, delete 

14from tsfpga.vivado.common import get_vivado_version 

15 

16 

17class VivadoSimlibCommon: 

18 

19 """ 

20 Class for handling Vivado simlib used for simulation. Keeps track of when a 

21 (re)compile is needed. 

22 

23 This is a parent class that defines an interface and some common methods. 

24 See child classes for details: :class:`.VivadoSimlibGhdl`, :class:`.VivadoSimlibCommercial`. 

25 """ 

26 

27 # The version of this class. Can be bumped to force a re-compile if e.g. the TCL script changes 

28 # or the output folder structure is updated. 

29 _format_version_id = 2 

30 

31 # Set in child class to a list of strings. The libraries that shall be compiled and added to 

32 # VUnit project. 

33 library_names = None 

34 

35 # Set in child class to a pathlib.Path object. The path to the "vivado" executable. 

36 _vivado_path = None 

37 

38 # Set in child class to a pathlib.Path object. The path where simlib shall be compiled. 

39 output_path = None 

40 

41 def compile_if_needed(self): 

42 """ 

43 Compile if needed (if :meth:`compile_is_needed <.compile_is_needed>` condition is not 

44 fulfilled). 

45 """ 

46 if self.compile_is_needed: 

47 self.compile() 

48 return True 

49 return False 

50 

51 @property 

52 def compile_is_needed(self): 

53 """ 

54 If there is compiled simlib available that matches 

55 

56 * Operating system 

57 * Vivado version 

58 * Simulator version 

59 

60 then there should not be a recompile. 

61 

62 .. note:: 

63 Child implementations might add further conditions. 

64 

65 Return: 

66 True if compiled simlib is not available. False otherwise. 

67 """ 

68 if self._done_token.exists(): 

69 return False 

70 return True 

71 

72 def compile(self): 

73 """ 

74 Compile simlib. 

75 """ 

76 delete(self._done_token) 

77 print(f"Compiling Vivado simlib in {self.output_path}") 

78 

79 self._compile() 

80 

81 create_file(self._done_token, "Done!") 

82 

83 def _compile(self): 

84 """ 

85 Compile simlib. 

86 """ 

87 raise NotImplementedError() 

88 

89 def add_to_vunit_project(self): 

90 """ 

91 Add the compiled simlib to your VUnit project. 

92 """ 

93 self._add_to_vunit_project() 

94 

95 def _add_to_vunit_project(self): 

96 raise NotImplementedError() 

97 

98 @property 

99 def artifact_name(self): 

100 """ 

101 str: The name of the folder where simlib is or will be compiled. 

102 Follows a format ``vivado-simlib-WW.XX.YY.ZZ`` suitable for storage and versioning 

103 in Artifactory. 

104 """ 

105 return self.output_path.name 

106 

107 def to_archive(self): 

108 """ 

109 Compress compiled simlib to an archive. 

110 

111 Return: 

112 pathlib.Path: Path to the archive. 

113 """ 

114 make_archive(self.output_path, "zip", self.output_path) 

115 archive = self.output_path.parent / (self.output_path.name + ".zip") 

116 return archive 

117 

118 def from_archive(self, archive): 

119 """ 

120 Unpack compiled simlib from an existing archive. 

121 

122 Arguments: 

123 archive (pathlib.Path): Path to a zip archive with previously compiled simlib. 

124 """ 

125 with zipfile.ZipFile(archive, "r") as zip_handle: 

126 zip_handle.extractall(self.output_path) 

127 

128 def _get_version_tag(self): 

129 tag = "vivado-simlib-" 

130 tag += self._get_operating_system_tag() 

131 tag += f".{self._get_vivado_version_tag()}" 

132 tag += f".{self._get_simulator_tag()}" 

133 tag += f".format_{self._format_version_id}" 

134 

135 return tag 

136 

137 def _get_operating_system_tag(self): 

138 """ 

139 Return e.g. "linux". 

140 """ 

141 return self._format_version(platform.system()) 

142 

143 def _get_vivado_version_tag(self): 

144 """ 

145 Return e.g. "vivado_2021_2". 

146 """ 

147 vivado_version = get_vivado_version(self._vivado_path) 

148 

149 return self._format_version(f"vivado_{vivado_version}") 

150 

151 def _get_simulator_tag(self): 

152 raise NotImplementedError() 

153 

154 @staticmethod 

155 def _format_version(version): 

156 """ 

157 Format version string to something suitable for artifactory versioning. 

158 """ 

159 return version.replace(".", "_").replace("-", "_").lower() 

160 

161 @property 

162 def _done_token(self): 

163 """ 

164 Path to "done" token file. 

165 """ 

166 return self.output_path / "done.txt"