Coverage for pyEDAA/Launcher/__init__.py: 41%
80 statements
« prev ^ index » next coverage.py v7.6.9, created at 2024-12-20 22:15 +0000
« prev ^ index » next coverage.py v7.6.9, created at 2024-12-20 22:15 +0000
1# ==================================================================================================================== #
2# _____ ____ _ _ _ _ #
3# _ __ _ _| ____| _ \ / \ / \ | | __ _ _ _ _ __ ___| |__ ___ _ __ #
4# | '_ \| | | | _| | | | |/ _ \ / _ \ | | / _` | | | | '_ \ / __| '_ \ / _ \ '__| #
5# | |_) | |_| | |___| |_| / ___ \ / ___ \ _| |__| (_| | |_| | | | | (__| | | | __/ | #
6# | .__/ \__, |_____|____/_/ \_\/_/ \_(_)_____\__,_|\__,_|_| |_|\___|_| |_|\___|_| #
7# |_| |___/ #
8# ==================================================================================================================== #
9# Authors: #
10# Stefan Unrein #
11# Patrick Lehmann #
12# #
13# License: #
14# ==================================================================================================================== #
15# Copyright 2021-2024 Stefan Unrein - Endingen, Germany #
16# #
17# Licensed under the Apache License, Version 2.0 (the "License"); #
18# you may not use this file except in compliance with the License. #
19# You may obtain a copy of the License at #
20# #
21# http://www.apache.org/licenses/LICENSE-2.0 #
22# #
23# Unless required by applicable law or agreed to in writing, software #
24# distributed under the License is distributed on an "AS IS" BASIS, #
25# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
26# See the License for the specific language governing permissions and #
27# limitations under the License. #
28# #
29# SPDX-License-Identifier: Apache-2.0 #
30# ==================================================================================================================== #
31#
32"""Start the correct Vivado Version based on version in `*.xpr`file."""
33__author__ = "Stefan Unrein"
34__email__ = "stefan.unrein@gmx.net"
35__copyright__ = "2021-2024, Stefan Unrein"
36__license__ = "Apache License, Version 2.0"
37__version__ = "0.1.0"
38__keywords__ = ["launcher", "version selector", "xilinx", "vivado"]
40from re import compile as re_compile
42from sys import exit, argv
43import subprocess
44from pathlib import Path
45from textwrap import dedent
46from time import sleep
47from typing import NoReturn, Generator
49from pyTooling.Decorators import export
52@export
53class Program:
54 """Program instance of pyEDAA.Launcher."""
56 vivadoBatchfile = Path("bin/vivado.bat")
57 vvglWrapperFile = Path("bin/unwrapped/win64.o/vvgl.exe")
59 versionLineRegExp = re_compile(r"^<!--\s*Product\sVersion:\s+Vivado\s+v(?P<major>\d+).(?P<minor>\d+)(?:.(?P<patch>\d+))?\s+\(64-bit\)\s+-->")
61 _projectFilePath: Path
64 def __init__(self, projectFilePath: Path) -> None:
65 """Initializer.
67 :param projectFilePath: Path to the ``*.xpr`` file.
68 :raises Exception: When the given ``*.xpr`` file doesn't exist.
69 """
70 if not projectFilePath.exists(): 70 ↛ 71line 70 didn't jump to line 71 because the condition on line 70 was never true
71 raise Exception(f"Vivado project file '{projectFilePath}' not found.") \
72 from FileNotFoundError(f"File '{projectFilePath}' not found.")
74 self._projectFilePath = projectFilePath
76 def GetVersion(self) -> str:
77 """Opens an ``*.xpr`` file and returns the Vivado version used to save this file.
79 :returns: Used Vivado version to save the given ``*.xpr`` file.
80 :raises Exception: When the version information isn't found in the file.
81 """
82 with self._projectFilePath.open("r", encoding="utf-8") as file:
83 for line in file: 83 ↛ 88line 83 didn't jump to line 88 because the loop on line 83 didn't complete
84 match = self.versionLineRegExp.match(line)
85 if match is not None:
86 return f"{match['major']}.{match['minor']}"
87 else:
88 raise Exception(f"Pattern not found in '{self._projectFilePath}'.")
90 @classmethod
91 def GetVivadoVersions(self, installPath: Path) -> Generator[str, None, None]:
92 """Scan a given directory for installed Vivado versions.
94 :param installPath: Xilinx installation directory.
95 :returns: A generator for a sequence of installed Vivado versions.
96 """
97 for item in installPath.iterdir():
98 if item.is_dir():
99 yield item.name
101 def StartVivado(self, xilinxInstallationPath: Path, version: str) -> NoReturn:
102 """Start the given Vivado version with an ``*.xpr`` file as parameter.
104 :param xilinxInstallationPath: Path to the Xilinx toolchain installations.
105 :param version: The Vivado version to start.
106 """
107 vivadoInstallationPath = xilinxInstallationPath / version
109 vvglWrapperPath = vivadoInstallationPath / self.vvglWrapperFile
110 vivadoBatchfilePath = vivadoInstallationPath / self.vivadoBatchfile
112 cmd = [str(vvglWrapperPath), str(vivadoBatchfilePath), str(self._projectFilePath)]
113 subprocess.Popen(cmd, cwd=self._projectFilePath.parent) # , creationflags=subprocess.DETACHED_PROCESS)
115 print("")
116 print(f"Opening project with Vivado {version}.")
118 sleep(2)
119 exit(0)
121 @classmethod
122 def PrintHelp(cls, scriptPath: Path) -> None:
123 """Print a help page.
125 :param scriptPath: Path to this script.
126 """
127 print(dedent(f"""\
128 Run-Path '{scriptPath}'
130 For using this Launcher, please bind the *.xpr file extension to this executable with:
131 * Put this executable into the Vivado installation folder. E.g: C:\\Xilinx\\Vivado\\
132 * Change *.xpr association: right-click -> open with -> VivadoManager.exe
133 """))
136@export
137def main() -> NoReturn:
138 """Entry point function.
140 It creates an instance of :class:`Program` and hands over the execution to the OOP world.
141 """
142 xilinxInstallationPath = Path.cwd()
143 scriptPath = Path(argv[0])
145 if (argc := len(argv)) == 0:
146 Program.PrintHelp(scriptPath)
148 print(f"Current path '{xilinxInstallationPath}' contains the following folders:")
149 for version in Program.GetVivadoVersions(xilinxInstallationPath):
150 print(f"* {version}")
152 print("")
153 print("Press any key to exit.")
155 # wait on user interaction
156 input()
157 exit(0)
159 elif argc == 1:
160 projectFileArgument = argv[1]
161 projectFilePath = Path(projectFileArgument)
163 program = Program(projectFilePath)
165 try:
166 versionFromXPRFile = program.GetVersion()
167 except Exception as ex:
168 print(f"[ERROR] {ex}")
169 exit(1)
171 for version in program.GetVivadoVersions(xilinxInstallationPath):
172 if version == versionFromXPRFile:
173 program.StartVivado(xilinxInstallationPath, versionFromXPRFile)
174 else:
175 vivadoPath = xilinxInstallationPath / versionFromXPRFile
176 print(dedent(f"""\
177 ERROR: Vivado version {versionFromXPRFile} not available at path '{vivadoPath}'. Please start manually!
179 Press any key to exit.
180 """))
182 # wait on user interaction
183 input()
184 exit(1)
187# Entry point
188if __name__ == "__main__": 188 ↛ 189line 188 didn't jump to line 189 because the condition on line 188 was never true
189 main()