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
« 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# --------------------------------------------------------------------------------------------------
9import platform
10from shutil import make_archive
11import zipfile
13from tsfpga.system_utils import create_file, delete
14from tsfpga.vivado.common import get_vivado_version
17class VivadoSimlibCommon:
19 """
20 Class for handling Vivado simlib used for simulation. Keeps track of when a
21 (re)compile is needed.
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 """
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
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
35 # Set in child class to a pathlib.Path object. The path to the "vivado" executable.
36 _vivado_path = None
38 # Set in child class to a pathlib.Path object. The path where simlib shall be compiled.
39 output_path = None
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
51 @property
52 def compile_is_needed(self):
53 """
54 If there is compiled simlib available that matches
56 * Operating system
57 * Vivado version
58 * Simulator version
60 then there should not be a recompile.
62 .. note::
63 Child implementations might add further conditions.
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
72 def compile(self):
73 """
74 Compile simlib.
75 """
76 delete(self._done_token)
77 print(f"Compiling Vivado simlib in {self.output_path}")
79 self._compile()
81 create_file(self._done_token, "Done!")
83 def _compile(self):
84 """
85 Compile simlib.
86 """
87 raise NotImplementedError()
89 def add_to_vunit_project(self):
90 """
91 Add the compiled simlib to your VUnit project.
92 """
93 self._add_to_vunit_project()
95 def _add_to_vunit_project(self):
96 raise NotImplementedError()
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
107 def to_archive(self):
108 """
109 Compress compiled simlib to an archive.
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
118 def from_archive(self, archive):
119 """
120 Unpack compiled simlib from an existing archive.
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)
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}"
135 return tag
137 def _get_operating_system_tag(self):
138 """
139 Return e.g. "linux".
140 """
141 return self._format_version(platform.system())
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)
149 return self._format_version(f"vivado_{vivado_version}")
151 def _get_simulator_tag(self):
152 raise NotImplementedError()
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()
161 @property
162 def _done_token(self):
163 """
164 Path to "done" token file.
165 """
166 return self.output_path / "done.txt"