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

211 statements  

« prev     ^ index     » next       coverage.py v7.14.1, created at 2026-06-12 23:17 +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 _supports2019ImpureFunctions: str #: True, if VHDL-2019 impure functions are supported. 

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

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

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

199 

200 def __init__( 

201 self, 

202 osvvmVersion: Nullable[YearMonthVersion] = None, 

203 vhdlVersion: Nullable[VHDLVersion] = None, 

204 toolVendor: Nullable[str] = None, 

205 toolName: Nullable[str] = None, 

206 toolVersion: Nullable[str] = None, 

207 supports2019Interface: Nullable[str] = None, 

208 supports2019ImpureFunctions: Nullable[str] = None, 

209 supports2019FilePath: Nullable[str] = None, 

210 supports2019AssertAPI: Nullable[str] = None, 

211 supports2019Integer64Bits: Nullable[str] = None 

212 ) -> None: 

213 """ 

214 Initialize OSVVM's setting variables. 

215 

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

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

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

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

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

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

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

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

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

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

226 

227 .. note:: 

228 

229 If not specified, the following values are used: 

230 

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

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

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

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

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

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

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

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

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

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

241 """ 

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

243 self._osvvmCreateVTI = "false" 

244 

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

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

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

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

249 

250 self._supportsDeferredConstants = "true" 

251 self._supports2008GenericPackages = "true" 

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

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

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

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

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

257 

258 @readonly 

259 def OSVVMVersion(self) -> YearMonthVersion: 

260 """ 

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

262 

263 :returns: The latest supported OSVVM version. 

264 """ 

265 return self._osvvmVersion 

266 

267 @readonly 

268 def OSVVMCreateVTI(self) -> str: 

269 """ 

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

271 

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

273 """ 

274 return self._osvvmCreateVTI 

275 

276 @readonly 

277 def VHDLVersion(self) -> VHDLVersion: 

278 """ 

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

280 

281 :returns: The default VHDL language revision. 

282 """ 

283 return self._vhdlVersion 

284 

285 @readonly 

286 def ToolVendor(self) -> str: 

287 """ 

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

289 

290 :returns: The tool vendor name. 

291 """ 

292 return self._toolVendor 

293 

294 @readonly 

295 def ToolName(self) -> str: 

296 """ 

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

298 

299 :returns: The tool's name. 

300 """ 

301 return self._toolName 

302 

303 @readonly 

304 def ToolVersion(self) -> str: 

305 """ 

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

307 

308 :returns: The tool's version. 

309 """ 

310 return self._toolVersion 

311 

312 @readonly 

313 def SupportsDeferredConstants(self) -> str: 

314 """ 

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

316 

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

318 """ 

319 return self._supportsDeferredConstants 

320 

321 @readonly 

322 def Supports2008GenericPackages(self) -> str: 

323 """ 

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

325 

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

327 """ 

328 return self._supports2008GenericPackages 

329 

330 @readonly 

331 def Supports2019ImpureFunctions(self) -> str: 

332 """ 

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

334 

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

336 """ 

337 return self._supports2019ImpureFunctions 

338 

339 @readonly 

340 def Supports2019Interface(self) -> str: 

341 """ 

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

343 

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

345 """ 

346 return self._supports2019Interface 

347 

348 @readonly 

349 def Supports2019ImpureFunctions(self) -> str: 

350 """ 

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

352 

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

354 """ 

355 return self._supports2019ImpureFunctions 

356 

357 @readonly 

358 def Supports2019FilePath(self) -> str: 

359 """ 

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

361 

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

363 """ 

364 return self._supports2019FilePath 

365 

366 @readonly 

367 def Supports2019AssertAPI(self) -> str: 

368 """ 

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

370 

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

372 """ 

373 return self._supports2019AssertAPI 

374 

375 @readonly 

376 def Supports2019Integer64Bits(self) -> str: 

377 """ 

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

379 

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

381 """ 

382 return self._supports2019Integer64Bits 

383 

384 

385@export 

386class OsvvmProFileProcessor(TclEnvironment): 

387 """ 

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

389 """ 

390 

391 def __init__( 

392 self, 

393 context: Nullable[Context] = None, 

394 osvvmVariables: Nullable[OsvvmVariables] = None 

395 ) -> None: 

396 """ 

397 Initialize an OSVVM-specific TCL execution environment. 

398 

399 :param context: The TCL execution context. 

400 :param osvvmVariables: OSVVM default settings. 

401 

402 .. rubric:: Initialization steps: 

403 

404 1. Initialize base-class. 

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

406 3. Overwrite predefined TCL procedures. |br| 

407 Avoid harmful or disturbing actions caused by these procedures. 

408 4. Register Python functions as TCL procedures. 

409 """ 

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

411 context = osvvmContext 

412 

413 super().__init__(context) 

414 

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

416 osvvmVariables = OsvvmVariables() 

417 

418 self.LoadOsvvmDefaults(osvvmVariables) 

419 self.OverwriteTclProcedures() 

420 self.RegisterTclProcedures() 

421 

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

423 """ 

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

425 

426 :param osvvmVariables: OSVVM settings object. 

427 

428 .. code-block:: TCL 

429 

430 namespace eval ::osvvm { 

431 variable OsvvmVersion "<Version>" 

432 variable CreateVti "false" 

433 variable VhdlVersion "<Version>" 

434 variable ToolVendor "<ToolVendor>" 

435 variable ToolName "<ToolName>" 

436 variable ToolNameVersion "<ToolVersion>" 

437 variable ToolSupportsDeferredConstants "true" 

438 variable ToolSupportsGenericPackages "true" 

439 variable FunctionalCoverageIntegratedInSimulator "default" 

440 variable Supports2019Interface "false" 

441 variable Supports2019ImpureFunctions "false" 

442 variable Supports2019FilePath "false" 

443 variable Supports2019AssertApi "false" 

444 variable Supports2019Integer64Bits "false" 

445 

446 variable ClockResetVersion $OsvvmVersion 

447 } 

448 """ 

449 match osvvmVariables.VHDLVersion: 

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

451 version = "2002" 

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

453 version = "2008" 

454 case VHDLVersion.VHDL2019: 

455 version = "2019" 

456 case _: 

457 version = "unsupported" 

458 

459 code = dedent(f"""\ 

460 namespace eval ::osvvm {{ 

461 variable OsvvmVersion "{osvvmVariables.OSVVMVersion}" 

462 variable CreateVti "{osvvmVariables.OSVVMCreateVTI}" 

463 variable VhdlVersion "{version}" 

464 variable ToolVendor "{osvvmVariables.ToolVendor}" 

465 variable ToolName "{osvvmVariables.ToolName}" 

466 variable ToolNameVersion "{osvvmVariables.ToolVersion}" 

467 variable ToolSupportsDeferredConstants "{osvvmVariables.SupportsDeferredConstants}" 

468 variable ToolSupportsGenericPackages "{osvvmVariables.Supports2008GenericPackages}" 

469 variable FunctionalCoverageIntegratedInSimulator "default" 

470 variable Supports2019Interface "{osvvmVariables.Supports2019Interface}" 

471 variable Supports2019ImpureFunctions "{osvvmVariables.Supports2019ImpureFunctions}" 

472 variable Supports2019FilePath "{osvvmVariables.Supports2019FilePath}" 

473 variable Supports2019AssertApi "{osvvmVariables.Supports2019AssertAPI}" 

474 variable Supports2019Integer64Bits "{osvvmVariables.Supports2019Integer64Bits}" 

475 

476 variable ClockResetVersion $OsvvmVersion 

477 }} 

478 """) 

479 

480 try: 

481 self._tcl.eval(code) 

482 except TclError as ex: 

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

484 

485 def OverwriteTclProcedures(self) -> None: 

486 """ 

487 Overwrite predefined TCL procedures. 

488 

489 .. rubric:: List of overwritten procedures: 

490 

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

492 """ 

493 self.RegisterPythonFunctionAsTclProcedure(noop, "puts") 

494 

495 def RegisterTclProcedures(self) -> None: 

496 """ 

497 Register Python functions as TCL procedures. 

498 

499 .. rubric:: List of registered procedures: 

500 

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

529 """ 

530 self.RegisterPythonFunctionAsTclProcedure(build) 

531 self.RegisterPythonFunctionAsTclProcedure(include) 

532 self.RegisterPythonFunctionAsTclProcedure(library) 

533 self.RegisterPythonFunctionAsTclProcedure(analyze) 

534 self.RegisterPythonFunctionAsTclProcedure(simulate) 

535 self.RegisterPythonFunctionAsTclProcedure(generic) 

536 

537 self.RegisterPythonFunctionAsTclProcedure(BuildName) 

538 self.RegisterPythonFunctionAsTclProcedure(NoNullRangeWarning) 

539 

540 self.RegisterPythonFunctionAsTclProcedure(TestSuite) 

541 self.RegisterPythonFunctionAsTclProcedure(TestName) 

542 self.RegisterPythonFunctionAsTclProcedure(RunTest) 

543 

544 self.RegisterPythonFunctionAsTclProcedure(SetVHDLVersion) 

545 self.RegisterPythonFunctionAsTclProcedure(GetVHDLVersion) 

546 self.RegisterPythonFunctionAsTclProcedure(SetCoverageAnalyzeEnable) 

547 self.RegisterPythonFunctionAsTclProcedure(SetCoverageSimulateEnable) 

548 

549 self.RegisterPythonFunctionAsTclProcedure(FileExists) 

550 self.RegisterPythonFunctionAsTclProcedure(DirectoryExists) 

551 self.RegisterPythonFunctionAsTclProcedure(ChangeWorkingDirectory) 

552 

553 self.RegisterPythonFunctionAsTclProcedure(FindOsvvmSettingsDirectory) 

554 self.RegisterPythonFunctionAsTclProcedure(CreateOsvvmScriptSettingsPkg) 

555 

556 self.RegisterPythonFunctionAsTclProcedure(ConstraintFile) 

557 self.RegisterPythonFunctionAsTclProcedure(ScopeToRef) 

558 self.RegisterPythonFunctionAsTclProcedure(ScopeToCell) 

559 

560 self.RegisterPythonFunctionAsTclProcedure(noop, "OpenBuildHtml") 

561 self.RegisterPythonFunctionAsTclProcedure(noop, "SetTranscriptType") 

562 self.RegisterPythonFunctionAsTclProcedure(noop, "GetTranscriptType") 

563 self.RegisterPythonFunctionAsTclProcedure(noop, "SetSimulatorResolution") 

564 self.RegisterPythonFunctionAsTclProcedure(noop, "GetSimulatorResolution") 

565 

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

567 """ 

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

569 

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

571 

572 .. seealso:: 

573 

574 * :meth:`LoadBuildFile` 

575 """ 

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

577 includeFile = self._context.IncludeFile(path) 

578 self.EvaluateProFile(includeFile) 

579 

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

581 """ 

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

583 

584 .. rubric:: inferring the build name: 

585 

586 1. From optional parameter ``buildName``. 

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

588 

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

590 :returns: The created build object. 

591 

592 .. seealso:: 

593 

594 * :meth:`LoadIncludeFile` 

595 """ 

596 if buildName is None: 

597 buildName = buildFile.stem 

598 

599 self._context.BeginBuild(buildName) 

600 includeFile = self._context.IncludeFile(buildFile) 

601 self.EvaluateProFile(includeFile) 

602 

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

604 return self._context.EndBuild() 

605 

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

607 """ 

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

609 

610 .. rubric:: inferring the project name: 

611 

612 1. From optional parameter ``projectName``. 

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

614 

615 :param regressionFile: 

616 :param projectName: 

617 :return: 

618 """ 

619 if projectName is None: 

620 projectName = regressionFile.stem 

621 

622 self.EvaluateProFile(regressionFile) 

623 

624 return self._context.ToProject(projectName) 

625 

626 

627@export 

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

629 """ 

630 Restore Python exceptions if known by the execution context. 

631 

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

633 :param context: The TCL execution context. 

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

635 

636 .. note:: 

637 

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

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

640 interfacing procedures and preserved in the TCL execution context. 

641 

642 This helper function restores these preserved exception objects. 

643 """ 

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

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

646 return lastException 

647 

648 return ex