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
« 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
39from pyTooling.Decorators import export, readonly
40from pyTooling.MetaClasses import ExtendedType
41from pyTooling.Versioning import YearMonthVersion
42from pyVHDLModel import VHDLVersion
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
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.
65 def __init__(self, context: Context) -> None:
66 """
67 Initialize a TCL execution environment.
69 :param context: The TCL execution context.
70 """
71 self._context = context
72 context._processor = self
74 self._tcl = Tcl()
75 self._procedures = {}
77 @readonly
78 def TCL(self) -> Tk:
79 """
80 Read-only property to access the embedded TCL interpreter instance (:attr:`_tcl`).
82 :returns: TCL interpreter instance.
83 """
84 return self._tcl
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`).
91 :returns: The dictionary of registered procedures.
92 """
93 return self._procedures
95 @readonly
96 def Context(self) -> Context:
97 """
98 Read-only property to access the TCL execution context (:attr:`_context`).
100 :returns: The TCL execution context.
101 """
102 return self._context
104 def RegisterPythonFunctionAsTclProcedure(self, pythonFunction: Callable, tclProcedureName: Nullable[str] = None) -> None:
105 """
106 Register a Python function as TCL procedure.
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__
115 self._tcl.createcommand(tclProcedureName, pythonFunction)
116 self._procedures[tclProcedureName] = pythonFunction
118 def EvaluateTclCode(self, tclCode: str) -> None:
119 """
120 Evaluate TCL source code.
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
136 def EvaluateProFile(self, path: Path) -> None:
137 """
138 Evaluate TCL source file.
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
152 def __setitem__(self, tclVariableName: str, value: Any) -> None:
153 """
154 Set a TCL variable to a specific value.
156 :param tclVariableName: Name of the TCL variable.
157 :param value: Value to be set.
158 """
159 self._tcl.setvar(tclVariableName, value)
161 def __getitem__(self, tclVariableName: str) -> None:
162 """
163 Return a TCL variable's value.
165 :param tclVariableName: Name of the TCL variable.
166 :returns: TCL variable's value.
167 """
168 return self._tcl.getvar(tclVariableName)
170 def __delitem__(self, tclVariableName: str) -> None:
171 """
172 Unset a TCL variable.
174 :param tclVariableName: Name of the TCL variable.
175 """
176 self._tcl.unsetvar(tclVariableName)
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.
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.
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.
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.
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.
227 .. note::
229 If not specified, the following values are used:
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"
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"
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"
258 @readonly
259 def OSVVMVersion(self) -> YearMonthVersion:
260 """
261 Read-only property to access the latest support OSVVM version (:attr:`_osvvmVersion`).
263 :returns: The latest supported OSVVM version.
264 """
265 return self._osvvmVersion
267 @readonly
268 def OSVVMCreateVTI(self) -> str:
269 """
270 Read-only property to access the task deriving VTI components (:attr:`_osvvmCreateVTI`).
272 :returns: The task if VTI components should be derived..
273 """
274 return self._osvvmCreateVTI
276 @readonly
277 def VHDLVersion(self) -> VHDLVersion:
278 """
279 Read-only property to access the default VHDL language revision (:attr:`_vhdlVersion`).
281 :returns: The default VHDL language revision.
282 """
283 return self._vhdlVersion
285 @readonly
286 def ToolVendor(self) -> str:
287 """
288 Read-only property to access the tool vendor name (:attr:`_toolVendor`).
290 :returns: The tool vendor name.
291 """
292 return self._toolVendor
294 @readonly
295 def ToolName(self) -> str:
296 """
297 Read-only property to access the tool's' name (:attr:`_toolName`).
299 :returns: The tool's name.
300 """
301 return self._toolName
303 @readonly
304 def ToolVersion(self) -> str:
305 """
306 Read-only property to access the tool's version (:attr:`_toolVersion`).
308 :returns: The tool's version.
309 """
310 return self._toolVersion
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`).
317 :returns: The VHDL feature flag if deferred constants is supported.
318 """
319 return self._supportsDeferredConstants
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`).
326 :returns: The VHDL-2008 feature flag if generic packages is supported.
327 """
328 return self._supports2008GenericPackages
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`).
335 :returns: The VHDL-2019 feature flag if impure functions are supported.
336 """
337 return self._supports2019ImpureFunctions
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`).
344 :returns: The VHDL-2019 feature flag if mode views are supported.
345 """
346 return self._supports2019Interface
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`).
353 :returns: The VHDL-2019 feature flag if impure functions are supported.
354 """
355 return self._supports2019ImpureFunctions
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`).
362 :returns: The VHDL-2019 feature flag if file path is supported.
363 """
364 return self._supports2019FilePath
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`).
371 :returns: The VHDL-2019 feature flag if assert API is supported.
372 """
373 return self._supports2019AssertAPI
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`).
380 :returns: The VHDL-2019 feature flag if 64-bit integers are supported.
381 """
382 return self._supports2019Integer64Bits
385@export
386class OsvvmProFileProcessor(TclEnvironment):
387 """
388 An OSVVM-specific TCL execution environment for ``*.pro`` files.
389 """
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.
399 :param context: The TCL execution context.
400 :param osvvmVariables: OSVVM default settings.
402 .. rubric:: Initialization steps:
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
413 super().__init__(context)
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()
418 self.LoadOsvvmDefaults(osvvmVariables)
419 self.OverwriteTclProcedures()
420 self.RegisterTclProcedures()
422 def LoadOsvvmDefaults(self, osvvmVariables: OsvvmVariables) -> None:
423 """
424 Create an OSVVM namespace and declare variables with default values.
426 :param osvvmVariables: OSVVM settings object.
428 .. code-block:: TCL
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"
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"
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}"
476 variable ClockResetVersion $OsvvmVersion
477 }}
478 """)
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
485 def OverwriteTclProcedures(self) -> None:
486 """
487 Overwrite predefined TCL procedures.
489 .. rubric:: List of overwritten procedures:
491 * `puts` |rarr| :func:`~pyEDAA.OSVVM.Project.Procedures.noop`
492 """
493 self.RegisterPythonFunctionAsTclProcedure(noop, "puts")
495 def RegisterTclProcedures(self) -> None:
496 """
497 Register Python functions as TCL procedures.
499 .. rubric:: List of registered procedures:
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)
537 self.RegisterPythonFunctionAsTclProcedure(BuildName)
538 self.RegisterPythonFunctionAsTclProcedure(NoNullRangeWarning)
540 self.RegisterPythonFunctionAsTclProcedure(TestSuite)
541 self.RegisterPythonFunctionAsTclProcedure(TestName)
542 self.RegisterPythonFunctionAsTclProcedure(RunTest)
544 self.RegisterPythonFunctionAsTclProcedure(SetVHDLVersion)
545 self.RegisterPythonFunctionAsTclProcedure(GetVHDLVersion)
546 self.RegisterPythonFunctionAsTclProcedure(SetCoverageAnalyzeEnable)
547 self.RegisterPythonFunctionAsTclProcedure(SetCoverageSimulateEnable)
549 self.RegisterPythonFunctionAsTclProcedure(FileExists)
550 self.RegisterPythonFunctionAsTclProcedure(DirectoryExists)
551 self.RegisterPythonFunctionAsTclProcedure(ChangeWorkingDirectory)
553 self.RegisterPythonFunctionAsTclProcedure(FindOsvvmSettingsDirectory)
554 self.RegisterPythonFunctionAsTclProcedure(CreateOsvvmScriptSettingsPkg)
556 self.RegisterPythonFunctionAsTclProcedure(ConstraintFile)
557 self.RegisterPythonFunctionAsTclProcedure(ScopeToRef)
558 self.RegisterPythonFunctionAsTclProcedure(ScopeToCell)
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")
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`).
570 :param path: Path to the ``*.pro`` file.
572 .. seealso::
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)
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.
584 .. rubric:: inferring the build name:
586 1. From optional parameter ``buildName``.
587 2. From ``*.pro`` file's filename.
589 :param path: Path to the ``*.pro`` file.
590 :returns: The created build object.
592 .. seealso::
594 * :meth:`LoadIncludeFile`
595 """
596 if buildName is None:
597 buildName = buildFile.stem
599 self._context.BeginBuild(buildName)
600 includeFile = self._context.IncludeFile(buildFile)
601 self.EvaluateProFile(includeFile)
603 # TODO: should a context be used with _context to restore _currentDirectory?
604 return self._context.EndBuild()
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.
610 .. rubric:: inferring the project name:
612 1. From optional parameter ``projectName``.
613 2. From ``*.pro`` file's filename.
615 :param regressionFile:
616 :param projectName:
617 :return:
618 """
619 if projectName is None:
620 projectName = regressionFile.stem
622 self.EvaluateProFile(regressionFile)
624 return self._context.ToProject(projectName)
627@export
628def getException(ex: Exception, context: Context) -> Exception:
629 """
630 Restore Python exceptions if known by the execution context.
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.
636 .. note::
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.
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
648 return ex