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
« 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
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 _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.
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.
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.
230 .. note::
232 If not specified, the following values are used:
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"
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"
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"
263 @readonly
264 def OSVVMVersion(self) -> YearMonthVersion:
265 """
266 Read-only property to access the latest support OSVVM version (:attr:`_osvvmVersion`).
268 :returns: The latest supported OSVVM version.
269 """
270 return self._osvvmVersion
272 @readonly
273 def OSVVMCreateVTI(self) -> str:
274 """
275 Read-only property to access the task deriving VTI components (:attr:`_osvvmCreateVTI`).
277 :returns: The task if VTI components should be derived..
278 """
279 return self._osvvmCreateVTI
281 @readonly
282 def VHDLVersion(self) -> VHDLVersion:
283 """
284 Read-only property to access the default VHDL language revision (:attr:`_vhdlVersion`).
286 :returns: The default VHDL language revision.
287 """
288 return self._vhdlVersion
290 @readonly
291 def ToolVendor(self) -> str:
292 """
293 Read-only property to access the tool vendor name (:attr:`_toolVendor`).
295 :returns: The tool vendor name.
296 """
297 return self._toolVendor
299 @readonly
300 def ToolName(self) -> str:
301 """
302 Read-only property to access the tool's' name (:attr:`_toolName`).
304 :returns: The tool's name.
305 """
306 return self._toolName
308 @readonly
309 def ToolVersion(self) -> str:
310 """
311 Read-only property to access the tool's version (:attr:`_toolVersion`).
313 :returns: The tool's version.
314 """
315 return self._toolVersion
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`).
322 :returns: The VHDL feature flag if deferred constants is supported.
323 """
324 return self._supportsDeferredConstants
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`).
331 :returns: The VHDL-2008 feature flag if generic packages is supported.
332 """
333 return self._supports2008GenericPackages
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`).
340 :returns: The VHDL-2019 feature flag if impure functions are supported.
341 """
342 return self._supports2019ImpureFunctions
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`).
349 :returns: The VHDL-2019 feature flag if mode views are supported.
350 """
351 return self._supports2019Interface
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`).
358 :returns: The VHDL-2019 feature flag if extended incomplete type generics are supported.
359 """
360 return self._supports2019Generics
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`).
367 :returns: The VHDL-2019 feature flag if impure functions are supported.
368 """
369 return self._supports2019ImpureFunctions
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`).
376 :returns: The VHDL-2019 feature flag if file path is supported.
377 """
378 return self._supports2019FilePath
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`).
385 :returns: The VHDL-2019 feature flag if assert API is supported.
386 """
387 return self._supports2019AssertAPI
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`).
394 :returns: The VHDL-2019 feature flag if 64-bit integers are supported.
395 """
396 return self._supports2019Integer64Bits
399@export
400class OsvvmProFileProcessor(TclEnvironment):
401 """
402 An OSVVM-specific TCL execution environment for ``*.pro`` files.
403 """
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.
413 :param context: The TCL execution context.
414 :param osvvmVariables: OSVVM default settings.
416 .. rubric:: Initialization steps:
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
427 super().__init__(context)
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()
432 self.LoadOsvvmDefaults(osvvmVariables)
433 self.OverwriteTclProcedures()
434 self.RegisterTclProcedures()
436 def LoadOsvvmDefaults(self, osvvmVariables: OsvvmVariables) -> None:
437 """
438 Create an OSVVM namespace and declare variables with default values.
440 :param osvvmVariables: OSVVM settings object.
442 .. code-block:: TCL
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"
460 variable ClockResetVersion $OsvvmVersion
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"
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}"
493 variable ClockResetVersion $OsvvmVersion
495 variable CreateVti "{osvvmVariables.OSVVMCreateVTI}"
496 variable OsvvmDevDeriveArchitectures "false"
497 }}
498 """)
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
505 def OverwriteTclProcedures(self) -> None:
506 """
507 Overwrite predefined TCL procedures.
509 .. rubric:: List of overwritten procedures:
511 * `puts` |rarr| :func:`~pyEDAA.OSVVM.Project.Procedures.noop`
512 """
513 self.RegisterPythonFunctionAsTclProcedure(noop, "puts")
515 def RegisterTclProcedures(self) -> None:
516 """
517 Register Python functions as TCL procedures.
519 .. rubric:: List of registered procedures:
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)
557 self.RegisterPythonFunctionAsTclProcedure(BuildName)
558 self.RegisterPythonFunctionAsTclProcedure(NoNullRangeWarning)
560 self.RegisterPythonFunctionAsTclProcedure(TestSuite)
561 self.RegisterPythonFunctionAsTclProcedure(TestName)
562 self.RegisterPythonFunctionAsTclProcedure(RunTest)
564 self.RegisterPythonFunctionAsTclProcedure(SetVHDLVersion)
565 self.RegisterPythonFunctionAsTclProcedure(GetVHDLVersion)
566 self.RegisterPythonFunctionAsTclProcedure(SetCoverageAnalyzeEnable)
567 self.RegisterPythonFunctionAsTclProcedure(SetCoverageSimulateEnable)
569 self.RegisterPythonFunctionAsTclProcedure(FileExists)
570 self.RegisterPythonFunctionAsTclProcedure(DirectoryExists)
571 self.RegisterPythonFunctionAsTclProcedure(ChangeWorkingDirectory)
573 self.RegisterPythonFunctionAsTclProcedure(FindOsvvmSettingsDirectory)
574 self.RegisterPythonFunctionAsTclProcedure(CreateOsvvmScriptSettingsPkg)
576 self.RegisterPythonFunctionAsTclProcedure(ConstraintFile)
577 self.RegisterPythonFunctionAsTclProcedure(ScopeToRef)
578 self.RegisterPythonFunctionAsTclProcedure(ScopeToCell)
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")
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`).
590 :param path: Path to the ``*.pro`` file.
592 .. seealso::
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)
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.
604 .. rubric:: inferring the build name:
606 1. From optional parameter ``buildName``.
607 2. From ``*.pro`` file's filename.
609 :param path: Path to the ``*.pro`` file.
610 :returns: The created build object.
612 .. seealso::
614 * :meth:`LoadIncludeFile`
615 """
616 if buildName is None:
617 buildName = buildFile.stem
619 self._context.BeginBuild(buildName)
620 includeFile = self._context.IncludeFile(buildFile)
621 self.EvaluateProFile(includeFile)
623 # TODO: should a context be used with _context to restore _currentDirectory?
624 return self._context.EndBuild()
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.
630 .. rubric:: inferring the project name:
632 1. From optional parameter ``projectName``.
633 2. From ``*.pro`` file's filename.
635 :param regressionFile:
636 :param projectName:
637 :return:
638 """
639 if projectName is None:
640 projectName = regressionFile.stem
642 self.EvaluateProFile(regressionFile)
644 return self._context.ToProject(projectName)
647@export
648def getException(ex: Exception, context: Context) -> Exception:
649 """
650 Restore Python exceptions if known by the execution context.
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.
656 .. note::
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.
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
668 return ex