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
« 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"]
40from pathlib import Path
41from typing import Dict, ClassVar, cast
43from pyTooling.Configuration import Dictionary
44from pyTooling.Decorators import export
45from pyTooling.Exceptions import ExceptionBase
46from pyTooling.Configuration.YAML import Configuration
48from .DataModel import (
49 Installation as DM_Installation,
50 Vendor as DM_Vendor,
51 Tool as DM_Tool,
52 ToolInstance as DM_ToolInstance
53)
56class ToolChainException(ExceptionBase):
57 """Base-class for all pyEDAA.ToolSetup specific exceptions."""
59class ConfigurationException(ExceptionBase):
60 """``ConfigurationException`` is raise while running configuration or database
61 tasks in pyIPCMI
62 """
64class SkipConfigurationException(ExceptionBase):
65 """``SkipConfigurationException`` is a :py:exc:`ConfigurationException`,
66 which can be skipped.
67 """
69class ConfigurationMixIn:
70 _config: Dictionary
72 def __init__(self, config: Dictionary):
73 self._config = config
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"]
84 super().__init__(installationDirectory, binaryDirectory, version, parent=parent)
85 ConfigurationMixIn.__init__(self, config)
88@export
89class Tool(DM_Tool, ConfigurationMixIn):
90 def __init__(self, config: Dictionary, parent: "Vendor"):
91 name = config.Key
93 super().__init__(name, parent=parent)
94 ConfigurationMixIn.__init__(self, config)
96 @property
97 def Default(self) -> ToolInstance:
98 return self._LoadVariant("Default")
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]
107 return instance
109 def _LoadAllVariants(self) -> None:
110 if self._allLoaded:
111 return
113 for key in self._config:
114 if key not in self._variants:
115 self._variants[key] = ToolInstance(self._config[key], parent=self)
117 self._allLoaded = True
120@export
121class Vendor(DM_Vendor, ConfigurationMixIn):
122 _toolClasses: ClassVar[Dict[str, Tool]]
124 def __init__(self, config: Dictionary, parent: "Installations"):
125 name = config.Key
126 installationDirectory = Path(config["InstallationDirectory"])
128 super().__init__(name, installationDirectory, parent=parent)
129 ConfigurationMixIn.__init__(self, config)
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]
139 return tool
141 def _LoadAllTools(self) -> None:
142 if self._allLoaded:
143 return
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)
150 self._allLoaded = True
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
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 }
177 def __init__(self, yamlFile: Path):
178 super().__init__()
179 self._config = Configuration(yamlFile)
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
186 return vendor
188 def _LoadAllVendors(self) -> None:
189 if self._allLoaded:
190 return
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)
197 self._allLoaded = True
199 @property
200 def Aldec(self) -> Aldec:
201 from .Aldec import Aldec
202 return cast(Aldec, self.__getitem__("Aldec"))
204 @property
205 def Altera(self) -> Altera:
206 from .IntelFPGA import Altera
207 return cast(Altera, self.__getitem__("Altera"))
209 @property
210 def IntelFPGA(self) -> IntelFPGA:
211 from .IntelFPGA import IntelFPGA
212 return cast(IntelFPGA, self.__getitem__("IntelFPGA"))
214 @property
215 def Lattice(self) -> Lattice:
216 from .Lattice import Lattice
217 return cast(Lattice, self.__getitem__("Lattice"))
219 @property
220 def MentorGraphics(self) -> MentorGraphics:
221 from .SiemensEDA import MentorGraphics
222 return cast(MentorGraphics, self.__getitem__("MentorGraphics"))
224 @property
225 def OpenSource(self) -> OpenSource:
226 from .OpenSource import OpenSource
227 return cast(OpenSource, self.__getitem__("OpenSource"))
229 @property
230 def SiemensEDA(self) -> SiemensEDA:
231 from .SiemensEDA import SiemensEDA
232 return cast(SiemensEDA, self.__getitem__("SiemensEDA"))
234 @property
235 def SystemTools(self) -> SystemTools:
236 from .SystemTools import SystemTools
237 return cast(SystemTools, self.__getitem__("SystemTools"))
239 @property
240 def Xilinx(self) -> Xilinx:
241 from .Xilinx import Xilinx
242 return cast(Xilinx, self.__getitem__("Xilinx"))
244 @property
245 def ActiveHDL(self) -> ActiveHDL:
246 raise NotImplementedError()
248 @property
249 def RivieraPRO(self) -> RivieraPRO:
250 raise NotImplementedError()
252 @property
253 def Diamond(self) -> Diamond:
254 raise NotImplementedError()
256 @property
257 def Quartus(self) -> Quartus:
258 raise NotImplementedError()
260 @property
261 def ModelSim(self) -> ModelSim:
262 raise NotImplementedError()
264 @property
265 def QuestaSim(self) -> QuestaSim:
266 raise NotImplementedError()
268 @property
269 def Vivado(self) -> Vivado:
270 raise NotImplementedError()
272 @property
273 def VivadoSDK(self) -> VivadoSDK:
274 raise NotImplementedError()
276 @property
277 def Vitis(self) -> Vitis:
278 raise NotImplementedError()