Coverage for pyEDAA/OSVVM/Project/TCL.py: 79%

199 statements  

« prev     ^ index     » next       coverage.py v7.15.1, created at 2026-07-13 18:15 +0000

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

2# _____ ____ _ _ ___ ______ ____ ____ __ # 

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

4# | '_ \| | | | _| | | | |/ _ \ / _ \ | | | \___ \\ \ / / \ \ / /| |\/| | # 

5# | |_) | |_| | |___| |_| / ___ \ / ___ \ | |_| |___) |\ V / \ V / | | | | # 

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

7# |_| |___/ # 

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

9# Authors: # 

10# Patrick Lehmann # 

11# # 

12# License: # 

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

14# Copyright 2025-2026 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""" 

32A TCL execution environment for OSVVM's ``*.pro`` files. 

33""" 

34from pathlib import Path 

35from textwrap import dedent 

36from tkinter import Tk, Tcl, TclError 

37from typing import Any, Dict, Callable, Optional as Nullable 

38 

39from pyTooling.Decorators import export, readonly 

40from pyTooling.MetaClasses import ExtendedType 

41from pyTooling.Versioning import YearMonthVersion 

42from pyVHDLModel import VHDLVersion 

43 

44from pyEDAA.OSVVM import OSVVMException 

45from pyEDAA.OSVVM.Project import Context, osvvmContext, Build, Project 

46from pyEDAA.OSVVM.Project.Procedures import noop, NoNullRangeWarning 

47from pyEDAA.OSVVM.Project.Procedures import FileExists, DirectoryExists, FindOsvvmSettingsDirectory 

48from pyEDAA.OSVVM.Project.Procedures import build, BuildName, include, library, analyze, simulate, generic 

49from pyEDAA.OSVVM.Project.Procedures import TestSuite, TestName, RunTest 

50from pyEDAA.OSVVM.Project.Procedures import ChangeWorkingDirectory, CreateOsvvmScriptSettingsPkg 

51from pyEDAA.OSVVM.Project.Procedures import SetVHDLVersion, GetVHDLVersion 

52from pyEDAA.OSVVM.Project.Procedures import SetCoverageAnalyzeEnable, SetCoverageSimulateEnable 

53from pyEDAA.OSVVM.Project.Procedures import ConstraintFile, ScopeToRef, ScopeToCell 

54 

55 

56@export 

57class TclEnvironment(metaclass=ExtendedType, slots=True): 

58 """ 

59 A TCL execution environment wrapping an embedded TCL interpreter based on :class:`tkinter.Tcl`. 

60 """ 

61 _tcl: Tk #: The embedded TCL interpreter instance. 

62 _procedures: Dict[str, Callable] #: A dictionary of registered TCL procedures implemented by Python functions. 

63 _context: Context #: The TCL execution context. 

64 

65 def __init__(self, context: Context) -> None: 

66 """ 

67 Initialize a TCL execution environment. 

68 

69 :param context: The TCL execution context. 

70 """ 

71 self._context = context 

72 context._processor = self 

73 

74 self._tcl = Tcl() 

75 self._procedures = {} 

76 

77 @readonly 

78 def TCL(self) -> Tk: 

79 """ 

80 Read-only property to access the embedded TCL interpreter instance (:attr:`_tcl`). 

81 

82 :returns: TCL interpreter instance. 

83 """ 

84 return self._tcl 

85 

86 @readonly 

87 def Procedures(self) -> Dict[str, Callable]: 

88 """ 

89 Read-only property to access the dictionary of registered TCL procedures implemented by Python functions (:attr:`_procedures`). 

90 

91 :returns: The dictionary of registered procedures. 

92 """ 

93 return self._procedures 

94 

95 @readonly 

96 def Context(self) -> Context: 

97 """ 

98 Read-only property to access the TCL execution context (:attr:`_context`). 

99 

100 :returns: The TCL execution context. 

101 """ 

102 return self._context 

103 

104 def RegisterPythonFunctionAsTclProcedure(self, pythonFunction: Callable, tclProcedureName: Nullable[str] = None) -> None: 

105 """ 

106 Register a Python function as TCL procedure. 

107 

108 :param pythonFunction: The Python function to be registered. 

109 :param tclProcedureName: Optional, name of the TCl procedure. |br| 

110 Default: derived the TCL procedure name from Python function name. 

111 """ 

112 if tclProcedureName is None: 

113 tclProcedureName = pythonFunction.__name__ 

114 

115 self._tcl.createcommand(tclProcedureName, pythonFunction) 

116 self._procedures[tclProcedureName] = pythonFunction 

117 

118 def EvaluateTclCode(self, tclCode: str) -> None: 

119 """ 

120 Evaluate TCL source code. 

121 

122 :param tclCode: TCL source code to evaluate. 

123 :raises OSVVMException: When a :exc:`~tkinter.TclError` is caught while executing the TCL source code. |br| 

124 In case the error is unspecific, :func:`~pyEDAA.OSVVM.Project.TCL.getException` is used to 

125 look up and restore an exception, potentially coming from Python code called within TCL 

126 code. 

127 """ 

128 try: 

129 self._tcl.eval(tclCode) 

130 except TclError as e: 

131 e = getException(e, self._context) 

132 ex = OSVVMException(f"Caught TclError while evaluating TCL code.") 

133 ex.add_note(tclCode) 

134 raise ex from e 

135 

136 def EvaluateProFile(self, path: Path) -> None: 

137 """ 

138 Evaluate TCL source file. 

139 

140 :param path: Path to a TCL source file for evaluation. 

141 :raises OSVVMException: When a :exc:`~tkinter.TclError` is caught while executing the TCL source code. |br| 

142 In case the error is unspecific, :func:`~pyEDAA.OSVVM.Project.TCL.getException` is used to 

143 look up and restore an exception, potentially coming from Python code called within TCL 

144 code. 

145 """ 

146 try: 

147 self._tcl.evalfile(str(path)) 

148 except TclError as e: 

149 ex = getException(e, self._context) 

150 raise OSVVMException(f"Caught TclError while processing '{self._context.WorkingDirectory / path}'.") from ex 

151 

152 def __setitem__(self, tclVariableName: str, value: Any) -> None: 

153 """ 

154 Set a TCL variable to a specific value. 

155 

156 :param tclVariableName: Name of the TCL variable. 

157 :param value: Value to be set. 

158 """ 

159 self._tcl.setvar(tclVariableName, value) 

160 

161 def __getitem__(self, tclVariableName: str) -> None: 

162 """ 

163 Return a TCL variable's value. 

164 

165 :param tclVariableName: Name of the TCL variable. 

166 :returns: TCL variable's value. 

167 """ 

168 return self._tcl.getvar(tclVariableName) 

169 

170 def __delitem__(self, tclVariableName: str) -> None: 

171 """ 

172 Unset a TCL variable. 

173 

174 :param tclVariableName: Name of the TCL variable. 

175 """ 

176 self._tcl.unsetvar(tclVariableName) 

177 

178 

179@export 

180class OsvvmVariables(metaclass=ExtendedType, slots=True): 

181 """ 

182 A class representing OSVVM's setting variables. 

183 """ 

184 _osvvmVersion: YearMonthVersion #: Latest supported OSVVM version. 

185 _osvvmCreateVTI: str #: Create derived VTI components. Not supported. 

186 

187 _vhdlVersion: VHDLVersion #: Default VHDL language revision. 

188 _toolVendor: str #: Name of the tool vendor. 

189 _toolName: str #: Name of the tool. 

190 _toolVersion: str #: Version of the tool. 

191 

192 _supportsDeferredConstants: str #: True, if deferred constants are supported. 

193 _supports2008GenericPackages: str #: True, if VHDL-2008 generic packages are supported. 

194 _supports2019Interface: str #: True, if VHDL-2019 mode views are supported. 

195 _supports2019Generics: str #: True, if VHDL-2019 extended incomplete type generics are supported. 

196 _supports2019ImpureFunctions: str #: True, if VHDL-2019 impure functions are supported. 

197 _supports2019FilePath: str #: True, if VHDL-2019 file path is supported. 

198 _supports2019AssertAPI: str #: True, if VHDL-2019 assert API is support 

199 _supports2019Integer64Bits: str #: True, if VHDL-2019 64-bit integers are supported. 

200 

201 def __init__( 

202 self, 

203 osvvmVersion: Nullable[YearMonthVersion] = None, 

204 vhdlVersion: Nullable[VHDLVersion] = None, 

205 toolVendor: Nullable[str] = None, 

206 toolName: Nullable[str] = None, 

207 toolVersion: Nullable[str] = None, 

208 supports2019Interface: Nullable[str] = None, 

209 supports2019Generics: Nullable[str] = None, 

210 supports2019ImpureFunctions: Nullable[str] = None, 

211 supports2019FilePath: Nullable[str] = None, 

212 supports2019AssertAPI: Nullable[str] = None, 

213 supports2019Integer64Bits: Nullable[str] = None 

214 ) -> None: 

215 """ 

216 Initialize OSVVM's setting variables. 

217 

218 :param osvvmVersion: Optional, latest supported OSVVM version. 

219 :param vhdlVersion: Optional, default VHDL language revision. 

220 :param toolVendor: Optional, name of the tool vendor. 

221 :param toolName: Optional, name of the tool. 

222 :param toolVersion: Optional, version of the tool. 

223 :param supports2019Interface: Optional, VHDL-2019 mode views are supported. 

224 :param supports2019Generics: Optional, VHDL-2019 extended incomplete type generics are supported. 

225 :param supports2019ImpureFunctions: Optional, VHDL-2019 impure functions are supported. 

226 :param supports2019FilePath: Optional, VHDL-2019 file path is supported. 

227 :param supports2019AssertAPI: Optional, VHDL-2019 assert API is support 

228 :param supports2019Integer64Bits: Optional, VHDL-2019 64-bit integers are supported. 

229 

230 .. note:: 

231 

232 If not specified, the following values are used: 

233 

234 * OSVVM version = :pycode:`YearMonthVersion.Parse("2026.01")` 

235 * VHDL version = :pycode:`VHDLVersion.VHDL2008` 

236 * Tool vendor = :pycode:`"EDA²"` 

237 * Tool name = :pycode:`"pyEDAA.ProjectModel"` 

238 * Tool version = :pycode:`"0.1"` 

239 * Supports VHDL-2019 interface = :pycode:`"false"` 

240 * Supports VHDL-2019 generics = :pycode:`"false"` 

241 * Supports VHDL-2019 impure functions = :pycode:`"false"` 

242 * Supports VHDL-2019 file path = :pycode:`"false"` 

243 * Supports VHDL-2019 assert API = :pycode:`"false"` 

244 * Supports VHDL-2019 64-bit integers = :pycode:`"false"` 

245 """ 

246 self._osvvmVersion = osvvmVersion if osvvmVersion is not None else YearMonthVersion.Parse("2026.01") 

247 self._osvvmCreateVTI = "false" 

248 

249 self._vhdlVersion = vhdlVersion if vhdlVersion is not None else VHDLVersion.VHDL2008 

250 self._toolVendor = toolVendor if toolVendor is not None else "EDA²" 

251 self._toolName = toolName if toolName is not None else "pyEDAA.ProjectModel" 

252 self._toolVersion = toolVersion if toolVersion is not None else "0.1" 

253 

254 self._supportsDeferredConstants = "true" 

255 self._supports2008GenericPackages = "true" 

256 self._supports2019Interface = supports2019Interface if supports2019Interface is not None else "false" 

257 self._supports2019Generics = supports2019Generics if supports2019Generics is not None else "false" 

258 self._supports2019ImpureFunctions = supports2019ImpureFunctions if supports2019ImpureFunctions is not None else "false" 

259 self._supports2019FilePath = supports2019FilePath if supports2019FilePath is not None else "false" 

260 self._supports2019AssertAPI = supports2019AssertAPI if supports2019AssertAPI is not None else "false" 

261 self._supports2019Integer64Bits = supports2019Integer64Bits if supports2019Integer64Bits is not None else "false" 

262 

263 @readonly 

264 def OSVVMVersion(self) -> YearMonthVersion: 

265 """ 

266 Read-only property to access the latest support OSVVM version (:attr:`_osvvmVersion`). 

267 

268 :returns: The latest supported OSVVM version. 

269 """ 

270 return self._osvvmVersion 

271 

272 @readonly 

273 def OSVVMCreateVTI(self) -> str: 

274 """ 

275 Read-only property to access the task deriving VTI components (:attr:`_osvvmCreateVTI`). 

276 

277 :returns: The task if VTI components should be derived.. 

278 """ 

279 return self._osvvmCreateVTI 

280 

281 @readonly 

282 def VHDLVersion(self) -> VHDLVersion: 

283 """ 

284 Read-only property to access the default VHDL language revision (:attr:`_vhdlVersion`). 

285 

286 :returns: The default VHDL language revision. 

287 """ 

288 return self._vhdlVersion 

289 

290 @readonly 

291 def ToolVendor(self) -> str: 

292 """ 

293 Read-only property to access the tool vendor name (:attr:`_toolVendor`). 

294 

295 :returns: The tool vendor name. 

296 """ 

297 return self._toolVendor 

298 

299 @readonly 

300 def ToolName(self) -> str: 

301 """ 

302 Read-only property to access the tool's' name (:attr:`_toolName`). 

303 

304 :returns: The tool's name. 

305 """ 

306 return self._toolName 

307 

308 @readonly 

309 def ToolVersion(self) -> str: 

310 """ 

311 Read-only property to access the tool's version (:attr:`_toolVersion`). 

312 

313 :returns: The tool's version. 

314 """ 

315 return self._toolVersion 

316 

317 @readonly 

318 def SupportsDeferredConstants(self) -> str: 

319 """ 

320 Read-only property to access the VHDL feature flag if deferred constants are supported (:attr:`_supportsDeferredConstants`). 

321 

322 :returns: The VHDL feature flag if deferred constants is supported. 

323 """ 

324 return self._supportsDeferredConstants 

325 

326 @readonly 

327 def Supports2008GenericPackages(self) -> str: 

328 """ 

329 Read-only property to access the VHDL-2008 feature flag if generic packages are supported (:attr:`_supports2008GenericPackages`). 

330 

331 :returns: The VHDL-2008 feature flag if generic packages is supported. 

332 """ 

333 return self._supports2008GenericPackages 

334 

335 @readonly 

336 def Supports2019ImpureFunctions(self) -> str: 

337 """ 

338 Read-only property to access the VHDL-2019 feature flag if impure functions are supported (:attr:`_supports2019ImpureFunctions`). 

339 

340 :returns: The VHDL-2019 feature flag if impure functions are supported. 

341 """ 

342 return self._supports2019ImpureFunctions 

343 

344 @readonly 

345 def Supports2019Interface(self) -> str: 

346 """ 

347 Read-only property to access the VHDL-2019 feature flag if mode views (interfaces) are supported (:attr:`_supports2019Interface`). 

348 

349 :returns: The VHDL-2019 feature flag if mode views are supported. 

350 """ 

351 return self._supports2019Interface 

352 

353 @readonly 

354 def Supports2019Generics(self) -> str: 

355 """ 

356 Read-only property to access the VHDL-2019 feature flag if extended incomplete type generics are supported (:attr:`_supports2019Generics`). 

357 

358 :returns: The VHDL-2019 feature flag if extended incomplete type generics are supported. 

359 """ 

360 return self._supports2019Generics 

361 

362 @readonly 

363 def Supports2019ImpureFunctions(self) -> str: 

364 """ 

365 Read-only property to access the VHDL-2019 feature flag if impure functions are supported (:attr:`_supports2019ImpureFunctions`). 

366 

367 :returns: The VHDL-2019 feature flag if impure functions are supported. 

368 """ 

369 return self._supports2019ImpureFunctions 

370 

371 @readonly 

372 def Supports2019FilePath(self) -> str: 

373 """ 

374 Read-only property to access the VHDL-2019 feature flag if file path is supported (:attr:`_supports2019FilePath`). 

375 

376 :returns: The VHDL-2019 feature flag if file path is supported. 

377 """ 

378 return self._supports2019FilePath 

379 

380 @readonly 

381 def Supports2019AssertAPI(self) -> str: 

382 """ 

383 Read-only property to access the VHDL-2019 feature flag if assert API is supported (:attr:`_supports2019AssertAPI`). 

384 

385 :returns: The VHDL-2019 feature flag if assert API is supported. 

386 """ 

387 return self._supports2019AssertAPI 

388 

389 @readonly 

390 def Supports2019Integer64Bits(self) -> str: 

391 """ 

392 Read-only property to access the VHDL-2019 feature flag if 64-bit integers are supported (:attr:`_supports2019Integer64Bits`). 

393 

394 :returns: The VHDL-2019 feature flag if 64-bit integers are supported. 

395 """ 

396 return self._supports2019Integer64Bits 

397 

398 

399@export 

400class OsvvmProFileProcessor(TclEnvironment): 

401 """ 

402 An OSVVM-specific TCL execution environment for ``*.pro`` files. 

403 """ 

404 

405 def __init__( 

406 self, 

407 context: Nullable[Context] = None, 

408 osvvmVariables: Nullable[OsvvmVariables] = None 

409 ) -> None: 

410 """ 

411 Initialize an OSVVM-specific TCL execution environment. 

412 

413 :param context: The TCL execution context. 

414 :param osvvmVariables: OSVVM default settings. 

415 

416 .. rubric:: Initialization steps: 

417 

418 1. Initialize base-class. 

419 2. Load OSVVM default value into ``::osvvm::`` namespace variables. 

420 3. Overwrite predefined TCL procedures. |br| 

421 Avoid harmful or disturbing actions caused by these procedures. 

422 4. Register Python functions as TCL procedures. 

423 """ 

424 if context is None: 424 ↛ 427line 424 didn't jump to line 427 because the condition on line 424 was always true

425 context = osvvmContext 

426 

427 super().__init__(context) 

428 

429 if osvvmVariables is None: 429 ↛ 432line 429 didn't jump to line 432 because the condition on line 429 was always true

430 osvvmVariables = OsvvmVariables() 

431 

432 self.LoadOsvvmDefaults(osvvmVariables) 

433 self.OverwriteTclProcedures() 

434 self.RegisterTclProcedures() 

435 

436 def LoadOsvvmDefaults(self, osvvmVariables: OsvvmVariables) -> None: 

437 """ 

438 Create an OSVVM namespace and declare variables with default values. 

439 

440 :param osvvmVariables: OSVVM settings object. 

441 

442 .. code-block:: TCL 

443 

444 namespace eval ::osvvm { 

445 variable OsvvmVersion "<Version>" 

446 variable VhdlVersion "<Version>" 

447 variable ToolVendor "<ToolVendor>" 

448 variable ToolName "<ToolName>" 

449 variable ToolNameVersion "<ToolVersion>" 

450 variable ToolSupportsDeferredConstants "true" 

451 variable ToolSupportsGenericPackages "true" 

452 variable FunctionalCoverageIntegratedInSimulator "default" 

453 variable Supports2019Interface "false" 

454 variable Supports2019Generics "false" 

455 variable Supports2019ImpureFunctions "false" 

456 variable Supports2019FilePath "false" 

457 variable Supports2019AssertApi "false" 

458 variable Supports2019Integer64Bits "false" 

459 

460 variable ClockResetVersion $OsvvmVersion 

461 

462 variable CreateVti "false" 

463 variable OsvvmDevDeriveArchitectures "false" 

464 } 

465 """ 

466 match osvvmVariables.VHDLVersion: 

467 case VHDLVersion.VHDL2002: 467 ↛ 468line 467 didn't jump to line 468 because the pattern on line 467 never matched

468 version = "2002" 

469 case VHDLVersion.VHDL2008: 469 ↛ 471line 469 didn't jump to line 471 because the pattern on line 469 always matched

470 version = "2008" 

471 case VHDLVersion.VHDL2019: 

472 version = "2019" 

473 case _: 

474 version = "unsupported" 

475 

476 code = dedent(f"""\ 

477 namespace eval ::osvvm {{ 

478 variable OsvvmVersion "{osvvmVariables.OSVVMVersion}" 

479 variable VhdlVersion "{version}" 

480 variable ToolVendor "{osvvmVariables.ToolVendor}" 

481 variable ToolName "{osvvmVariables.ToolName}" 

482 variable ToolNameVersion "{osvvmVariables.ToolVersion}" 

483 variable ToolSupportsDeferredConstants "{osvvmVariables.SupportsDeferredConstants}" 

484 variable ToolSupportsGenericPackages "{osvvmVariables.Supports2008GenericPackages}" 

485 variable FunctionalCoverageIntegratedInSimulator "default" 

486 variable Supports2019Interface "{osvvmVariables.Supports2019Interface}" 

487 variable Supports2019Generics "{osvvmVariables.Supports2019Generics}" 

488 variable Supports2019ImpureFunctions "{osvvmVariables.Supports2019ImpureFunctions}" 

489 variable Supports2019FilePath "{osvvmVariables.Supports2019FilePath}" 

490 variable Supports2019AssertApi "{osvvmVariables.Supports2019AssertAPI}" 

491 variable Supports2019Integer64Bits "{osvvmVariables.Supports2019Integer64Bits}" 

492 

493 variable ClockResetVersion $OsvvmVersion 

494 

495 variable CreateVti "{osvvmVariables.OSVVMCreateVTI}" 

496 variable OsvvmDevDeriveArchitectures "false" 

497 }} 

498 """) 

499 

500 try: 

501 self._tcl.eval(code) 

502 except TclError as ex: 

503 raise OSVVMException(f"TCL error occurred, when initializing OSVVM variables.") from ex 

504 

505 def OverwriteTclProcedures(self) -> None: 

506 """ 

507 Overwrite predefined TCL procedures. 

508 

509 .. rubric:: List of overwritten procedures: 

510 

511 * `puts` |rarr| :func:`~pyEDAA.OSVVM.Project.Procedures.noop` 

512 """ 

513 self.RegisterPythonFunctionAsTclProcedure(noop, "puts") 

514 

515 def RegisterTclProcedures(self) -> None: 

516 """ 

517 Register Python functions as TCL procedures. 

518 

519 .. rubric:: List of registered procedures: 

520 

521 * ``build`` |rarr| :func:`~pyEDAA.OSVVM.Project.Procedures.build` 

522 * ``include`` |rarr| :func:`~pyEDAA.OSVVM.Project.Procedures.include` 

523 * ``library`` |rarr| :func:`~pyEDAA.OSVVM.Project.Procedures.library` 

524 * ``analyze`` |rarr| :func:`~pyEDAA.OSVVM.Project.Procedures.analyze` 

525 * ``simulate`` |rarr| :func:`~pyEDAA.OSVVM.Project.Procedures.simulate` 

526 * ``generic`` |rarr| :func:`~pyEDAA.OSVVM.Project.Procedures.generic` 

527 * ``BuildName`` |rarr| :func:`~pyEDAA.OSVVM.Project.Procedures.BuildName` 

528 * ``NoNullRangeWarning`` |rarr| :func:`~pyEDAA.OSVVM.Project.Procedures.NoNullRangeWarning` 

529 * ``TestSuite`` |rarr| :func:`~pyEDAA.OSVVM.Project.Procedures.TestSuite` 

530 * ``TestName`` |rarr| :func:`~pyEDAA.OSVVM.Project.Procedures.TestName` 

531 * ``RunTest`` |rarr| :func:`~pyEDAA.OSVVM.Project.Procedures.RunTest` 

532 * ``SetVHDLVersion`` |rarr| :func:`~pyEDAA.OSVVM.Project.Procedures.SetVHDLVersion` 

533 * ``GetVHDLVersion`` |rarr| :func:`~pyEDAA.OSVVM.Project.Procedures.GetVHDLVersion` 

534 * ``SetCoverageAnalyzeEnable`` |rarr| :func:`~pyEDAA.OSVVM.Project.Procedures.SetCoverageAnalyzeEnable` 

535 * ``SetCoverageSimulateEnable`` |rarr| :func:`~pyEDAA.OSVVM.Project.Procedures.SetCoverageSimulateEnable` 

536 * ``FileExists`` |rarr| :func:`~pyEDAA.OSVVM.Project.Procedures.FileExists` 

537 * ``DirectoryExists`` |rarr| :func:`~pyEDAA.OSVVM.Project.Procedures.DirectoryExists` 

538 * ``ChangeWorkingDirectory`` |rarr| :func:`~pyEDAA.OSVVM.Project.Procedures.ChangeWorkingDirectory` 

539 * ``FindOsvvmSettingsDirectory`` |rarr| :func:`~pyEDAA.OSVVM.Project.Procedures.FindOsvvmSettingsDirectory` 

540 * ``CreateOsvvmScriptSettingsPkg`` |rarr| :func:`~pyEDAA.OSVVM.Project.Procedures.CreateOsvvmScriptSettingsPkg` 

541 * ``ConstraintFile`` |rarr| :func:`~pyEDAA.OSVVM.Project.Procedures.ConstraintFile` 

542 * ``ScopeToRef`` |rarr| :func:`~pyEDAA.OSVVM.Project.Procedures.ScopeToRef` 

543 * ``ScopeToCell`` |rarr| :func:`~pyEDAA.OSVVM.Project.Procedures.ScopeToCell` 

544 * ``OpenBuildHtml`` |rarr| :func:`~pyEDAA.OSVVM.Project.Procedures.noop` 

545 * ``SetTranscriptType`` |rarr| :func:`~pyEDAA.OSVVM.Project.Procedures.noop` 

546 * ``GetTranscriptType`` |rarr| :func:`~pyEDAA.OSVVM.Project.Procedures.noop` 

547 * ``SetSimulatorResolution`` |rarr| :func:`~pyEDAA.OSVVM.Project.Procedures.noop` 

548 * ``GetSimulatorResolution`` |rarr| :func:`~pyEDAA.OSVVM.Project.Procedures.noop` 

549 """ 

550 self.RegisterPythonFunctionAsTclProcedure(build) 

551 self.RegisterPythonFunctionAsTclProcedure(include) 

552 self.RegisterPythonFunctionAsTclProcedure(library) 

553 self.RegisterPythonFunctionAsTclProcedure(analyze) 

554 self.RegisterPythonFunctionAsTclProcedure(simulate) 

555 self.RegisterPythonFunctionAsTclProcedure(generic) 

556 

557 self.RegisterPythonFunctionAsTclProcedure(BuildName) 

558 self.RegisterPythonFunctionAsTclProcedure(NoNullRangeWarning) 

559 

560 self.RegisterPythonFunctionAsTclProcedure(TestSuite) 

561 self.RegisterPythonFunctionAsTclProcedure(TestName) 

562 self.RegisterPythonFunctionAsTclProcedure(RunTest) 

563 

564 self.RegisterPythonFunctionAsTclProcedure(SetVHDLVersion) 

565 self.RegisterPythonFunctionAsTclProcedure(GetVHDLVersion) 

566 self.RegisterPythonFunctionAsTclProcedure(SetCoverageAnalyzeEnable) 

567 self.RegisterPythonFunctionAsTclProcedure(SetCoverageSimulateEnable) 

568 

569 self.RegisterPythonFunctionAsTclProcedure(FileExists) 

570 self.RegisterPythonFunctionAsTclProcedure(DirectoryExists) 

571 self.RegisterPythonFunctionAsTclProcedure(ChangeWorkingDirectory) 

572 

573 self.RegisterPythonFunctionAsTclProcedure(FindOsvvmSettingsDirectory) 

574 self.RegisterPythonFunctionAsTclProcedure(CreateOsvvmScriptSettingsPkg) 

575 

576 self.RegisterPythonFunctionAsTclProcedure(ConstraintFile) 

577 self.RegisterPythonFunctionAsTclProcedure(ScopeToRef) 

578 self.RegisterPythonFunctionAsTclProcedure(ScopeToCell) 

579 

580 self.RegisterPythonFunctionAsTclProcedure(noop, "OpenBuildHtml") 

581 self.RegisterPythonFunctionAsTclProcedure(noop, "SetTranscriptType") 

582 self.RegisterPythonFunctionAsTclProcedure(noop, "GetTranscriptType") 

583 self.RegisterPythonFunctionAsTclProcedure(noop, "SetSimulatorResolution") 

584 self.RegisterPythonFunctionAsTclProcedure(noop, "GetSimulatorResolution") 

585 

586 def LoadIncludeFile(self, path: Path) -> None: 

587 """ 

588 Load an OSVVM ``*.pro`` file for inclusion (not as a root level build, see :meth:`LoadBuildFile`). 

589 

590 :param path: Path to the ``*.pro`` file. 

591 

592 .. seealso:: 

593 

594 * :meth:`LoadBuildFile` 

595 """ 

596 # TODO: should a context be used with _context to restore _currentDirectory? 

597 includeFile = self._context.IncludeFile(path) 

598 self.EvaluateProFile(includeFile) 

599 

600 def LoadBuildFile(self, buildFile: Path, buildName: Nullable[str] = None) -> Build: 

601 """ 

602 Load an OSVVM ``*.pro`` file as build creating a new build context. 

603 

604 .. rubric:: inferring the build name: 

605 

606 1. From optional parameter ``buildName``. 

607 2. From ``*.pro`` file's filename. 

608 

609 :param path: Path to the ``*.pro`` file. 

610 :returns: The created build object. 

611 

612 .. seealso:: 

613 

614 * :meth:`LoadIncludeFile` 

615 """ 

616 if buildName is None: 

617 buildName = buildFile.stem 

618 

619 self._context.BeginBuild(buildName) 

620 includeFile = self._context.IncludeFile(buildFile) 

621 self.EvaluateProFile(includeFile) 

622 

623 # TODO: should a context be used with _context to restore _currentDirectory? 

624 return self._context.EndBuild() 

625 

626 def LoadRegressionFile(self, regressionFile: Path, projectName: Nullable[str] = None) -> Project: 

627 """ 

628 Load a TCL file as a regression file and create a project from it. 

629 

630 .. rubric:: inferring the project name: 

631 

632 1. From optional parameter ``projectName``. 

633 2. From ``*.pro`` file's filename. 

634 

635 :param regressionFile: 

636 :param projectName: 

637 :return: 

638 """ 

639 if projectName is None: 

640 projectName = regressionFile.stem 

641 

642 self.EvaluateProFile(regressionFile) 

643 

644 return self._context.ToProject(projectName) 

645 

646 

647@export 

648def getException(ex: Exception, context: Context) -> Exception: 

649 """ 

650 Restore Python exceptions if known by the execution context. 

651 

652 :param ex: Original exception (usually a :exc:`~tkinter.TclError`). 

653 :param context: The TCL execution context. 

654 :returns: The original Python exception, if the context preserved an exception, otherwise the given TCLError. 

655 

656 .. note:: 

657 

658 When executing Python code within TCL, where TCL again is run within Python, TCL doesn't forward Python exceptions 

659 through the TCL layer back into Python. Therefore, last seen Python exceptions are caught in the Python-TCL 

660 interfacing procedures and preserved in the TCL execution context. 

661 

662 This helper function restores these preserved exception objects. 

663 """ 

664 if str(ex) == "": 664 ↛ 668line 664 didn't jump to line 668 because the condition on line 664 was always true

665 if (lastException := context.ClearLastException()) is not None: 665 ↛ 668line 665 didn't jump to line 668 because the condition on line 665 was always true

666 return lastException 

667 

668 return ex