Coverage for pyEDAA/ToolSetup/__init__.py: 67%

157 statements  

« prev     ^ index     » next       coverage.py v7.8.0, created at 2025-05-16 22:23 +0000

1# ==================================================================================================================== # 

2# _____ ____ _ _ ____ __ _ # 

3# _ __ _ _| ____| _ \ / \ / \ / ___|___ _ __ / _(_) __ _ _ _ _ __ ___ # 

4# | '_ \| | | | _| | | | |/ _ \ / _ \ | | / _ \| '_ \| |_| |/ _` | | | | '__/ _ \ # 

5# | |_) | |_| | |___| |_| / ___ \ / ___ \ | |__| (_) | | | | _| | (_| | |_| | | | __/ # 

6# | .__/ \__, |_____|____/_/ \_\/_/ \_(_)____\___/|_| |_|_| |_|\__, |\__,_|_| \___| # 

7# |_| |___/ |___/ # 

8# ==================================================================================================================== # 

9# Authors: # 

10# Patrick Lehmann # 

11# # 

12# License: # 

13# ==================================================================================================================== # 

14# Copyright 2014-2025 Patrick Lehmann - Boetzingen, Germany # 

15# # 

16# Licensed under the Apache License, Version 2.0 (the "License"); # 

17# you may not use this file except in compliance with the License. # 

18# You may obtain a copy of the License at # 

19# # 

20# http://www.apache.org/licenses/LICENSE-2.0 # 

21# # 

22# Unless required by applicable law or agreed to in writing, software # 

23# distributed under the License is distributed on an "AS IS" BASIS, # 

24# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # 

25# See the License for the specific language governing permissions and # 

26# limitations under the License. # 

27# # 

28# SPDX-License-Identifier: Apache-2.0 # 

29# ==================================================================================================================== # 

30# 

31"""Package to support configuring EDA tools for usage with pyEDAA.CLITool.""" 

32__author__ = "Patrick Lehmann" 

33__email__ = "Paebbels@gmail.com" 

34__copyright__ = "2014-2025, Patrick Lehmann" 

35__license__ = "Apache License, Version 2.0" 

36__version__ = "0.4.0" 

37__keywords__ = ["configuration", "eda", "installation", "selection"] 

38 

39 

40from pathlib import Path 

41from typing import Dict, ClassVar, cast 

42 

43from pyTooling.Configuration import Dictionary 

44from pyTooling.Decorators import export 

45from pyTooling.Exceptions import ExceptionBase 

46from pyTooling.Configuration.YAML import Configuration 

47 

48from .DataModel import ( 

49 Installation as DM_Installation, 

50 Vendor as DM_Vendor, 

51 Tool as DM_Tool, 

52 ToolInstance as DM_ToolInstance 

53) 

54 

55 

56class ToolChainException(ExceptionBase): 

57 """Base-class for all pyEDAA.ToolSetup specific exceptions.""" 

58 

59class ConfigurationException(ExceptionBase): 

60 """``ConfigurationException`` is raise while running configuration or database 

61 tasks in pyIPCMI 

62 """ 

63 

64class SkipConfigurationException(ExceptionBase): 

65 """``SkipConfigurationException`` is a :py:exc:`ConfigurationException`, 

66 which can be skipped. 

67 """ 

68 

69class ConfigurationMixIn: 

70 _config: Dictionary 

71 

72 def __init__(self, config: Dictionary): 

73 self._config = config 

74 

75 

76@export 

77class ToolInstance(DM_ToolInstance, ConfigurationMixIn): 

78 def __init__(self, config: Dictionary, parent: "Tool"): 

79 name = config.Key 

80 installationDirectory = Path(config["InstallationDirectory"]) 

81 binaryDirectory = Path(config["BinaryDirectory"]) 

82 version = config["Version"] 

83 

84 super().__init__(installationDirectory, binaryDirectory, version, parent=parent) 

85 ConfigurationMixIn.__init__(self, config) 

86 

87 

88@export 

89class Tool(DM_Tool, ConfigurationMixIn): 

90 def __init__(self, config: Dictionary, parent: "Vendor"): 

91 name = config.Key 

92 

93 super().__init__(name, parent=parent) 

94 ConfigurationMixIn.__init__(self, config) 

95 

96 @property 

97 def Default(self) -> ToolInstance: 

98 return self._LoadVariant("Default") 

99 

100 def _LoadVariant(self, key: str) -> ToolInstance: 

101 if key not in self._variants: 101 ↛ 105line 101 didn't jump to line 105 because the condition on line 101 was always true

102 instance = self._instanceClass(self._config[key], parent=self) 

103 self._variants[key] = instance 

104 else: 

105 instance = self._variants[key] 

106 

107 return instance 

108 

109 def _LoadAllVariants(self) -> None: 

110 if self._allLoaded: 

111 return 

112 

113 for key in self._config: 

114 if key not in self._variants: 

115 self._variants[key] = ToolInstance(self._config[key], parent=self) 

116 

117 self._allLoaded = True 

118 

119 

120@export 

121class Vendor(DM_Vendor, ConfigurationMixIn): 

122 _toolClasses: ClassVar[Dict[str, Tool]] 

123 

124 def __init__(self, config: Dictionary, parent: "Installations"): 

125 name = config.Key 

126 installationDirectory = Path(config["InstallationDirectory"]) 

127 

128 super().__init__(name, installationDirectory, parent=parent) 

129 ConfigurationMixIn.__init__(self, config) 

130 

131 def _LoadTool(self, key: str) -> Tool: 

132 if key not in self._tools: 132 ↛ 137line 132 didn't jump to line 137 because the condition on line 132 was always true

133 cls = self._toolClasses[key] 

134 tool = cls(self._config[key], parent=self) 

135 self._tools[key] = tool 

136 else: 

137 tool = self._tools[key] 

138 

139 return tool 

140 

141 def _LoadAllTools(self) -> None: 

142 if self._allLoaded: 

143 return 

144 

145 for key in self._config: 

146 if key not in self._tools: 

147 cls = self._toolClasses[key] 

148 self._tools[key] = cls(self._config[key], parent=self) 

149 

150 self._allLoaded = True 

151 

152 

153@export 

154class Installations(DM_Installation): 

155 from .Aldec import ActiveHDL, RivieraPRO, Aldec 

156 from .OpenSource.GHDL import GHDL 

157 from .IntelFPGA import Quartus, Altera, IntelFPGA 

158 from .Lattice import Diamond, Lattice 

159 from .OpenSource import OpenSource 

160 from .OpenSource.GTKWave import GTKWave 

161 from .SiemensEDA import ModelSim, QuestaSim, MentorGraphics 

162 from .SystemTools import Git, SystemTools 

163 from .Xilinx import ISE, Vivado, VivadoSDK, Vitis, Xilinx 

164 

165 _config: Configuration 

166 _vendorClasses: Dict[str, Vendor] = { 

167 "Aldec": Aldec, 

168 "Altera": Altera, 

169 "IntelFPGA": IntelFPGA, 

170 "Lattice": Lattice, 

171 "MentorGraphics": MentorGraphics, 

172 "Xilinx": Xilinx, 

173 "SystemTools": SystemTools, 

174 "OpenSource": OpenSource 

175 } 

176 

177 def __init__(self, yamlFile: Path): 

178 super().__init__() 

179 self._config = Configuration(yamlFile) 

180 

181 def _LoadVendor(self, key: str) -> Vendor: 

182 cls = self._vendorClasses[key] 

183 vendor = cls(self._config["Installations"][key], parent=self) 

184 self._vendors[key] = vendor 

185 

186 return vendor 

187 

188 def _LoadAllVendors(self) -> None: 

189 if self._allLoaded: 

190 return 

191 

192 for key in self._config["Installations"]: 

193 if key not in self._vendors: 

194 cls = self._vendorClasses[key] 

195 self._vendors[key] = cls(self._config["Installations"][key], parent=self) 

196 

197 self._allLoaded = True 

198 

199 @property 

200 def Aldec(self) -> Aldec: 

201 from .Aldec import Aldec 

202 return cast(Aldec, self.__getitem__("Aldec")) 

203 

204 @property 

205 def Altera(self) -> Altera: 

206 from .IntelFPGA import Altera 

207 return cast(Altera, self.__getitem__("Altera")) 

208 

209 @property 

210 def IntelFPGA(self) -> IntelFPGA: 

211 from .IntelFPGA import IntelFPGA 

212 return cast(IntelFPGA, self.__getitem__("IntelFPGA")) 

213 

214 @property 

215 def Lattice(self) -> Lattice: 

216 from .Lattice import Lattice 

217 return cast(Lattice, self.__getitem__("Lattice")) 

218 

219 @property 

220 def MentorGraphics(self) -> MentorGraphics: 

221 from .SiemensEDA import MentorGraphics 

222 return cast(MentorGraphics, self.__getitem__("MentorGraphics")) 

223 

224 @property 

225 def OpenSource(self) -> OpenSource: 

226 from .OpenSource import OpenSource 

227 return cast(OpenSource, self.__getitem__("OpenSource")) 

228 

229 @property 

230 def SiemensEDA(self) -> SiemensEDA: 

231 from .SiemensEDA import SiemensEDA 

232 return cast(SiemensEDA, self.__getitem__("SiemensEDA")) 

233 

234 @property 

235 def SystemTools(self) -> SystemTools: 

236 from .SystemTools import SystemTools 

237 return cast(SystemTools, self.__getitem__("SystemTools")) 

238 

239 @property 

240 def Xilinx(self) -> Xilinx: 

241 from .Xilinx import Xilinx 

242 return cast(Xilinx, self.__getitem__("Xilinx")) 

243 

244 @property 

245 def ActiveHDL(self) -> ActiveHDL: 

246 raise NotImplementedError() 

247 

248 @property 

249 def RivieraPRO(self) -> RivieraPRO: 

250 raise NotImplementedError() 

251 

252 @property 

253 def Diamond(self) -> Diamond: 

254 raise NotImplementedError() 

255 

256 @property 

257 def Quartus(self) -> Quartus: 

258 raise NotImplementedError() 

259 

260 @property 

261 def ModelSim(self) -> ModelSim: 

262 raise NotImplementedError() 

263 

264 @property 

265 def QuestaSim(self) -> QuestaSim: 

266 raise NotImplementedError() 

267 

268 @property 

269 def Vivado(self) -> Vivado: 

270 raise NotImplementedError() 

271 

272 @property 

273 def VivadoSDK(self) -> VivadoSDK: 

274 raise NotImplementedError() 

275 

276 @property 

277 def Vitis(self) -> Vitis: 

278 raise NotImplementedError()