vunit-python-bridge 0.2.0__py3-none-any.whl → 0.4.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- vunit_python_bridge/__init__.py +14 -40
- vunit_python_bridge/bin/vunit_python_bridge-cp310-win_amd64.dll +0 -0
- vunit_python_bridge/bin/vunit_python_bridge-cp311-win_amd64.dll +0 -0
- vunit_python_bridge/bin/vunit_python_bridge-cp312-win_amd64.dll +0 -0
- vunit_python_bridge/bin/vunit_python_bridge-cp313-win_amd64.dll +0 -0
- vunit_python_bridge/bin/vunit_python_bridge-cp314-win_amd64.dll +0 -0
- vunit_python_bridge/bin/vunit_python_bridge-cp315-win_amd64.dll +0 -0
- vunit_python_bridge/bridge.py +128 -25
- vunit_python_bridge/hdl/src/python_context.vhd +1 -0
- vunit_python_bridge/hdl/src/python_ffi_pkg_bridge.vhd +26 -14
- vunit_python_bridge/hdl/src/python_object_pkg.vhd +916 -0
- vunit_python_bridge/hdl/src/python_pkg.vhd +202 -16
- vunit_python_bridge/hdl/tools/generate_python_pkg.py +282 -14
- vunit_python_bridge/hdl/tools/python_object_pkg.vhd.in +255 -0
- vunit_python_bridge/hdl/tools/python_pkg.vhd.in +18 -16
- vunit_python_bridge/native/vhpi.c +223 -0
- vunit_python_bridge/native_library.py +76 -41
- vunit_python_bridge/runtime.py +91 -5
- vunit_python_bridge/simulator_hooks.py +48 -15
- vunit_python_bridge/vunit_pkg.toml +1 -1
- {vunit_python_bridge-0.2.0.dist-info → vunit_python_bridge-0.4.0.dist-info}/METADATA +11 -6
- vunit_python_bridge-0.4.0.dist-info/RECORD +34 -0
- vunit_python_bridge/foreign_application.py +0 -90
- vunit_python_bridge/hdl/src/python_pkg_vhpi.vhd +0 -284
- vunit_python_bridge/native/vhpi/python_pkg.c +0 -125
- vunit_python_bridge/native/vhpi/python_pkg.h +0 -31
- vunit_python_bridge/native/vhpi/python_pkg_vhpi.c +0 -366
- vunit_python_bridge-0.2.0.dist-info/RECORD +0 -36
- {vunit_python_bridge-0.2.0.dist-info → vunit_python_bridge-0.4.0.dist-info}/WHEEL +0 -0
- {vunit_python_bridge-0.2.0.dist-info → vunit_python_bridge-0.4.0.dist-info}/licenses/LICENSE +0 -0
- {vunit_python_bridge-0.2.0.dist-info → vunit_python_bridge-0.4.0.dist-info}/top_level.txt +0 -0
vunit_python_bridge/__init__.py
CHANGED
|
@@ -12,18 +12,17 @@ The VUnit package making Python callable from VHDL.
|
|
|
12
12
|
``python_pkg``/``python_context`` into the ``python_bridge`` library and sets up the foreign
|
|
13
13
|
language interface implementing them for the selected simulator:
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
the VUnit Python bridge, a small C library (native/*.c) embedding CPython in the simulator
|
|
16
|
+
process, called through VHPIDIRECT (NVC, GHDL), the FLI (Questa/ModelSim) or VHPI
|
|
17
|
+
(Riviera-PRO). A simulator provided by a VUnit package names its interface itself, see
|
|
18
|
+
bridge.bridge_simulators.
|
|
19
19
|
|
|
20
20
|
Modules:
|
|
21
21
|
|
|
22
22
|
* bridge: setup of the bridge, its configuration and its generated VHDL.
|
|
23
23
|
* native_library: compiles and caches the library on Linux and macOS, selects the prebuilt
|
|
24
24
|
DLL on Windows.
|
|
25
|
-
*
|
|
26
|
-
* simulator_hooks: makes NVC and GHDL find the library.
|
|
25
|
+
* simulator_hooks: makes the simulators find the library and its configuration.
|
|
27
26
|
* runtime: runs inside the simulator's embedded interpreter.
|
|
28
27
|
* file_base: the base directory of ``base_path``, ``set_relative_file_base``.
|
|
29
28
|
|
|
@@ -42,64 +41,39 @@ from .file_base import set_relative_file_base as set_relative_file_base
|
|
|
42
41
|
|
|
43
42
|
VHDL_PATH = Path(__file__).parent.resolve() / "hdl" / "src"
|
|
44
43
|
|
|
45
|
-
# The foreign language interface implementing the package for a simulator. VUnit says which
|
|
46
|
-
# simulator was selected, the package says how it is served: NVC and GHDL both go through
|
|
47
|
-
# VHPIDIRECT but bind the library differently, Questa/ModelSim goes through the FLI and
|
|
48
|
-
# Riviera-PRO/Active-HDL through a VHPI application of their own.
|
|
49
|
-
FOREIGN_LANGUAGE_INTERFACES = {
|
|
50
|
-
"nvc": "VHPIDIRECT_NVC",
|
|
51
|
-
"ghdl": "VHPIDIRECT_GHDL",
|
|
52
|
-
"modelsim": "FLI",
|
|
53
|
-
"rivierapro": "VHPI",
|
|
54
|
-
"activehdl": "VHPI",
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
# The simulators of the table, named as a user knows them
|
|
58
|
-
SUPPORTED_SIMULATORS = "NVC, GHDL, Questa/ModelSim, Riviera-PRO or Active-HDL"
|
|
59
|
-
|
|
60
44
|
|
|
61
45
|
def setup(context):
|
|
62
46
|
"""
|
|
63
47
|
Complete the addition of the package.
|
|
64
48
|
|
|
65
|
-
``vunit_pkg.toml`` lists the sources
|
|
66
|
-
foreign language interface of the selected simulator
|
|
67
|
-
Riviera-PRO/Active-HDL, the VUnit Python bridge for everyone else.
|
|
49
|
+
``vunit_pkg.toml`` lists the sources of the package, this adds the bridge for the
|
|
50
|
+
foreign language interface of the selected simulator.
|
|
68
51
|
"""
|
|
69
52
|
# pylint: disable=import-outside-toplevel
|
|
70
|
-
from .bridge import setup as setup_bridge
|
|
71
|
-
from .foreign_application import setup_vhpi_application
|
|
53
|
+
from .bridge import bridge_simulators, select_simulator, setup as setup_bridge
|
|
72
54
|
from . import simulator_hooks
|
|
73
55
|
|
|
74
56
|
simulator_name = context.simulator_name
|
|
57
|
+
simulators = bridge_simulators(simulator_name)
|
|
75
58
|
if simulator_name is None:
|
|
76
59
|
raise RuntimeError(
|
|
77
|
-
f"The vunit-python-bridge package requires {
|
|
60
|
+
f"The vunit-python-bridge package requires {', '.join(simulators)} but no simulator was found"
|
|
78
61
|
)
|
|
79
62
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
raise RuntimeError(
|
|
83
|
-
f"The vunit-python-bridge package requires {SUPPORTED_SIMULATORS}, "
|
|
84
|
-
f"it has no foreign language interface for {simulator_name}"
|
|
85
|
-
)
|
|
63
|
+
# Before anything is built, so a simulator the bridge cannot serve fails first
|
|
64
|
+
interface = select_simulator(simulators, simulator_name).interface
|
|
86
65
|
|
|
87
66
|
add_file_base_package(context)
|
|
88
67
|
|
|
89
|
-
if interface == "VHPI":
|
|
90
|
-
# Riviera-PRO/Active-HDL, the simulators served by the VHPI application
|
|
91
|
-
context.add_source_files(context.library.name, [VHDL_PATH / "python_pkg_vhpi.vhd"])
|
|
92
|
-
setup_vhpi_application(context.output_path, simulator_name, context.simulator_prefix)
|
|
93
|
-
return
|
|
94
|
-
|
|
95
68
|
bridge = setup_bridge(
|
|
96
69
|
context.output_path,
|
|
97
70
|
context.run_script_path,
|
|
98
71
|
simulator_name,
|
|
99
72
|
context.simulator_prefix,
|
|
100
73
|
context.simulator_backend,
|
|
74
|
+
interface,
|
|
101
75
|
)
|
|
102
76
|
|
|
103
77
|
context.add_source_files(context.library.name, list(bridge.vhdl_files))
|
|
104
78
|
|
|
105
|
-
simulator_hooks.register(context, bridge)
|
|
79
|
+
simulator_hooks.register(context, bridge, simulators)
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
vunit_python_bridge/bridge.py
CHANGED
|
@@ -13,7 +13,9 @@ import os
|
|
|
13
13
|
import re
|
|
14
14
|
import sys
|
|
15
15
|
from pathlib import Path
|
|
16
|
-
from typing import List, NamedTuple, Optional
|
|
16
|
+
from typing import Callable, Dict, List, NamedTuple, Optional
|
|
17
|
+
|
|
18
|
+
from vunit.sim_if.factory import SIMULATOR_FACTORY
|
|
17
19
|
|
|
18
20
|
from .native_library import (
|
|
19
21
|
LIBRARY_DIR_VARIABLE,
|
|
@@ -31,10 +33,20 @@ VHDL_SOURCE_PATH = PACKAGE_PATH / "hdl" / "src"
|
|
|
31
33
|
BRIDGE_PACKAGE_TEMPLATE = VHDL_SOURCE_PATH / "python_bridge_pkg.vhd.in"
|
|
32
34
|
CONFIG_FILE_NAME = "vunit_python_bridge.cfg"
|
|
33
35
|
|
|
34
|
-
# The
|
|
35
|
-
#
|
|
36
|
-
|
|
37
|
-
|
|
36
|
+
# The foreign language interface of each built-in VUnit simulator. VHPIDIRECT names the library
|
|
37
|
+
# by file name and the simulator hooks make the simulator load it, which GHDL does in its own way.
|
|
38
|
+
BUILTIN_SIMULATORS = {
|
|
39
|
+
"nvc": "VHPIDIRECT",
|
|
40
|
+
"ghdl": "VHPIDIRECT_GHDL",
|
|
41
|
+
"modelsim": "FLI",
|
|
42
|
+
"rivierapro": "VHPI",
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
# What the interface class of a simulator from a VUnit package defines instead, see
|
|
46
|
+
# docs/simulator_packages.rst
|
|
47
|
+
INTERFACE_ATTRIBUTE = "foreign_language_interface"
|
|
48
|
+
HOOKS_ATTRIBUTE = "native_library_hooks"
|
|
49
|
+
PACKAGE_INTERFACES = ("VHPIDIRECT", "FLI", "VHPI")
|
|
38
50
|
|
|
39
51
|
# GHDL backends that link the design ahead of time. For these the library
|
|
40
52
|
# token in the VHPIDIRECT attribute is passed to the linker instead of being
|
|
@@ -47,6 +59,16 @@ FOREIGN_PATTERN = re.compile(r"\{foreign:(\w+)\}")
|
|
|
47
59
|
SUBPROGRAM_PATTERN = re.compile(r"^ (impure function|procedure) (\w+)(\([^)]*\))?( return \w+)?;", re.MULTILINE)
|
|
48
60
|
|
|
49
61
|
|
|
62
|
+
class BridgeSimulator(NamedTuple):
|
|
63
|
+
"""
|
|
64
|
+
How the bridge serves a simulator: its foreign language interface and, for a simulator from a
|
|
65
|
+
VUnit package, the native_library_hooks that make it load the library (None for a built-in one).
|
|
66
|
+
"""
|
|
67
|
+
|
|
68
|
+
interface: str
|
|
69
|
+
native_library_hooks: Optional[Callable]
|
|
70
|
+
|
|
71
|
+
|
|
50
72
|
class PythonBridge(NamedTuple):
|
|
51
73
|
"""
|
|
52
74
|
A prepared bridge: the native library and the generated VHDL.
|
|
@@ -63,6 +85,7 @@ def setup(
|
|
|
63
85
|
simulator_name: Optional[str] = None,
|
|
64
86
|
simulator_prefix: Optional[str] = None,
|
|
65
87
|
simulator_backend: Optional[str] = None,
|
|
88
|
+
interface: Optional[str] = None,
|
|
66
89
|
) -> PythonBridge:
|
|
67
90
|
"""
|
|
68
91
|
Prepare the Python bridge for a project. Called by the package setup function.
|
|
@@ -73,25 +96,27 @@ def setup(
|
|
|
73
96
|
:param simulator_prefix: The path its executables were found in.
|
|
74
97
|
:param simulator_backend: How the installation found there was built, which for GHDL
|
|
75
98
|
is the code generator deciding how the library is bound.
|
|
99
|
+
:param interface: The foreign language interface, see bridge_simulators. None takes it from
|
|
100
|
+
there by simulator name.
|
|
76
101
|
:returns: The bridge. Its vhdl_files are to be added to the package library.
|
|
77
102
|
"""
|
|
78
|
-
if
|
|
79
|
-
|
|
80
|
-
f"The vunit-python-bridge package requires NVC, GHDL or Questa/ModelSim, "
|
|
81
|
-
f"it is not supported for {simulator_name}"
|
|
82
|
-
)
|
|
103
|
+
if interface is None and simulator_name is not None:
|
|
104
|
+
interface = select_simulator(bridge_simulators(simulator_name), simulator_name).interface
|
|
83
105
|
|
|
84
106
|
check_python_build()
|
|
85
107
|
check_windows_64bit_simulator(simulator_name, simulator_prefix)
|
|
86
108
|
|
|
87
|
-
is_fli =
|
|
88
|
-
|
|
109
|
+
is_fli = interface == "FLI"
|
|
110
|
+
is_vhpi = interface == "VHPI"
|
|
111
|
+
if (is_fli or is_vhpi) and simulator_prefix is None:
|
|
89
112
|
raise PythonBridgeError(
|
|
90
|
-
f"The FLI variant of the bridge is built against the {simulator_name}
|
|
113
|
+
f"The {'FLI' if is_fli else 'VHPI'} variant of the bridge is built against the {simulator_name} "
|
|
114
|
+
"installation, but it was not found"
|
|
91
115
|
)
|
|
92
116
|
|
|
93
117
|
root = Path(output_path) / "python_bridge"
|
|
94
|
-
|
|
118
|
+
front_end = "fli" if is_fli else "vhpi" if is_vhpi else None
|
|
119
|
+
library_file = _prepare_library(Path(simulator_prefix) if front_end else None, front_end)
|
|
95
120
|
run_script_dir = str(Path.cwd() if run_script_path is None else Path(run_script_path).resolve().parent)
|
|
96
121
|
# The configuration belongs to the project, the library may be shared. The simulator
|
|
97
122
|
# hooks tell the library where the configuration is.
|
|
@@ -99,13 +124,16 @@ def setup(
|
|
|
99
124
|
_write_if_changed(config_file, _config_text(run_script_dir))
|
|
100
125
|
|
|
101
126
|
# The foreign attribute string of an entry point: the name of its wrapper in native/fli.c
|
|
102
|
-
# and the library, by absolute path since Questa accepts it, for the FLI; the
|
|
103
|
-
#
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
127
|
+
# and the library, by absolute path since Questa accepts it, for the FLI; the library by
|
|
128
|
+
# absolute path without its suffix, which Riviera-PRO adds, and the entry point registered
|
|
129
|
+
# by native/vhpi.c for VHPI; the VHPIDIRECT library token and the entry point itself for
|
|
130
|
+
# VHPIDIRECT.
|
|
131
|
+
if is_fli:
|
|
132
|
+
foreign = f"fli_{{entry_point}} {library_file!s}"
|
|
133
|
+
elif is_vhpi:
|
|
134
|
+
foreign = f"VHPI {_vhpi_library_token(library_file)} {{entry_point}}"
|
|
135
|
+
else:
|
|
136
|
+
foreign = f"VHPIDIRECT {_vhpidirect_token(interface, simulator_backend, library_file)} {{entry_point}}"
|
|
109
137
|
bridge_package = root / "vhdl" / "python_bridge_pkg.vhd"
|
|
110
138
|
_write_if_changed(bridge_package, _render_bridge_package(foreign))
|
|
111
139
|
|
|
@@ -119,14 +147,75 @@ def setup(
|
|
|
119
147
|
)
|
|
120
148
|
|
|
121
149
|
|
|
122
|
-
def
|
|
150
|
+
def bridge_simulators(selected: Optional[str] = None) -> Dict[str, BridgeSimulator]:
|
|
151
|
+
"""
|
|
152
|
+
The simulators the bridge serves, by name: the built-in ones and every simulator VUnit knows,
|
|
153
|
+
from a simulator package, whose interface class defines foreign_language_interface and
|
|
154
|
+
native_library_hooks. The simulator packages are added to VUnit before the bridge. Only the
|
|
155
|
+
attributes of the selected simulator are checked, a class defining just one of them is
|
|
156
|
+
otherwise not a simulator the bridge serves.
|
|
157
|
+
"""
|
|
158
|
+
simulators = {name: BridgeSimulator(interface, None) for name, interface in BUILTIN_SIMULATORS.items()}
|
|
159
|
+
for simulator_class in SIMULATOR_FACTORY.supported_simulators():
|
|
160
|
+
interface = getattr(simulator_class, INTERFACE_ATTRIBUTE, None)
|
|
161
|
+
hooks = getattr(simulator_class, HOOKS_ATTRIBUTE, None)
|
|
162
|
+
if interface is None and hooks is None:
|
|
163
|
+
continue
|
|
164
|
+
if simulator_class.name == selected:
|
|
165
|
+
_check_attributes(simulator_class.name, interface, hooks)
|
|
166
|
+
elif interface is None or hooks is None:
|
|
167
|
+
continue
|
|
168
|
+
simulators[simulator_class.name] = BridgeSimulator(interface, hooks)
|
|
169
|
+
return simulators
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
def select_simulator(simulators: Dict[str, BridgeSimulator], name: str) -> BridgeSimulator:
|
|
173
|
+
"""
|
|
174
|
+
The simulator of the given name from bridge_simulators.
|
|
175
|
+
"""
|
|
176
|
+
if name not in simulators:
|
|
177
|
+
raise PythonBridgeError(
|
|
178
|
+
f"The vunit-python-bridge package requires {', '.join(simulators)}, or a simulator whose interface "
|
|
179
|
+
f"class says how it loads a native library, which {name} does not. Its simulator interface class must "
|
|
180
|
+
f"define {INTERFACE_ATTRIBUTE} ({', '.join(map(repr, PACKAGE_INTERFACES))}) and "
|
|
181
|
+
f"{HOOKS_ATTRIBUTE}(library_file), see 'Simulator packages' in the vunit-python-bridge documentation."
|
|
182
|
+
)
|
|
183
|
+
return simulators[name]
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
def _check_attributes(name: str, interface, hooks) -> None:
|
|
187
|
+
"""
|
|
188
|
+
Check the attributes a simulator interface class defines to be served by the bridge.
|
|
189
|
+
"""
|
|
190
|
+
for defined, missing, value in (
|
|
191
|
+
(INTERFACE_ATTRIBUTE, HOOKS_ATTRIBUTE, hooks),
|
|
192
|
+
(HOOKS_ATTRIBUTE, INTERFACE_ATTRIBUTE, interface),
|
|
193
|
+
):
|
|
194
|
+
if value is None:
|
|
195
|
+
raise PythonBridgeError(
|
|
196
|
+
f"The {name} simulator interface defines {defined} but not {missing}, "
|
|
197
|
+
"the vunit-python-bridge package needs both. Define it in the simulator interface class."
|
|
198
|
+
)
|
|
199
|
+
if interface not in PACKAGE_INTERFACES:
|
|
200
|
+
raise PythonBridgeError(
|
|
201
|
+
f"{INTERFACE_ATTRIBUTE} of the {name} simulator interface is {interface!r}, "
|
|
202
|
+
f"the vunit-python-bridge package knows {', '.join(map(repr, PACKAGE_INTERFACES))}"
|
|
203
|
+
)
|
|
204
|
+
if not callable(hooks):
|
|
205
|
+
raise PythonBridgeError(
|
|
206
|
+
f"{HOOKS_ATTRIBUTE} of the {name} simulator interface is not callable, it must be a static or "
|
|
207
|
+
"class method taking the library file"
|
|
208
|
+
)
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
def _prepare_library(simulator_prefix: Optional[Path], front_end: Optional[str]) -> Path:
|
|
123
212
|
"""
|
|
124
213
|
Prepare the library in the library directory, failing with a pointer to the variable
|
|
125
214
|
selecting another one when it cannot be written, e.g. a read-only home directory.
|
|
126
215
|
"""
|
|
127
216
|
directory = library_directory()
|
|
128
217
|
try:
|
|
129
|
-
return prepare_library(directory,
|
|
218
|
+
return prepare_library(directory, simulator_prefix, front_end)
|
|
130
219
|
except OSError as exc:
|
|
131
220
|
source = f"set by {LIBRARY_DIR_VARIABLE}" if os.environ.get(LIBRARY_DIR_VARIABLE) else "the default"
|
|
132
221
|
raise PythonBridgeError(
|
|
@@ -135,16 +224,30 @@ def _prepare_library(fli_prefix: Optional[Path]) -> Path:
|
|
|
135
224
|
) from exc
|
|
136
225
|
|
|
137
226
|
|
|
138
|
-
def _vhpidirect_token(
|
|
227
|
+
def _vhpidirect_token(interface: Optional[str], simulator_backend: Optional[str], library_file: Path) -> str:
|
|
139
228
|
"""
|
|
140
229
|
The library token of the VHPIDIRECT attributes: the file name the simulator dlopen()s,
|
|
141
230
|
or the linker flag of the GHDL backends that link the design ahead of time.
|
|
142
231
|
"""
|
|
143
|
-
if
|
|
232
|
+
if interface == "VHPIDIRECT_GHDL" and simulator_backend in GHDL_LINKING_BACKENDS:
|
|
144
233
|
return "-lvunit_python_bridge"
|
|
145
234
|
return library_file.name
|
|
146
235
|
|
|
147
236
|
|
|
237
|
+
def _vhpi_library_token(library_file: Path) -> str:
|
|
238
|
+
"""
|
|
239
|
+
The library of the VHPI attributes: its path without the suffix the simulator adds. The
|
|
240
|
+
attribute separates its parts by spaces, so the path cannot have any.
|
|
241
|
+
"""
|
|
242
|
+
token = str(library_file.with_suffix(""))
|
|
243
|
+
if any(character.isspace() for character in token):
|
|
244
|
+
raise PythonBridgeError(
|
|
245
|
+
f"The Python bridge library for VHPI is in {library_file.parent!s}, whose path has a space, which the "
|
|
246
|
+
f"VHPI foreign attribute cannot name. Set {LIBRARY_DIR_VARIABLE} to a directory without spaces."
|
|
247
|
+
)
|
|
248
|
+
return token
|
|
249
|
+
|
|
250
|
+
|
|
148
251
|
def _render_bridge_package(foreign: str) -> str:
|
|
149
252
|
"""
|
|
150
253
|
The generated python_bridge_pkg.vhd: the declarations of the template with the foreign
|
|
@@ -4,24 +4,18 @@
|
|
|
4
4
|
--
|
|
5
5
|
-- Copyright (c) 2014-2026, Lars Asplund lars.anders.asplund@gmail.com
|
|
6
6
|
--
|
|
7
|
-
-- The foreign language interface of the Python package for
|
|
8
|
-
-- implemented with the VUnit Python bridge (src/vunit_python_bridge)
|
|
9
|
-
--
|
|
10
|
-
--
|
|
11
|
-
--
|
|
12
|
-
--
|
|
13
|
-
-- * The subprograms are impure since they call impure foreign subprograms.
|
|
14
|
-
-- * Errors are reported as failures on the logger of the session they were
|
|
15
|
-
-- performed in rather than aborting the simulation directly, which makes
|
|
16
|
-
-- them observable from VHDL.
|
|
17
|
-
-- * Sessions other than the default one are supported.
|
|
7
|
+
-- The foreign language interface of the Python package for every simulator,
|
|
8
|
+
-- implemented with the VUnit Python bridge (src/vunit_python_bridge) over the
|
|
9
|
+
-- private python_bridge_pkg, which the setup function of the package generates.
|
|
10
|
+
-- The subprograms are impure since they call impure foreign subprograms. Errors
|
|
11
|
+
-- are reported as failures on the logger of the session they were performed in,
|
|
12
|
+
-- which makes them observable from VHDL.
|
|
18
13
|
--
|
|
19
14
|
-- The p_ prefixed declarations are the private primitives the bridge
|
|
20
|
-
-- operations of python_pkg are built on. They are not part of the API.
|
|
21
|
-
-- variants of this package declare the same primitives and implement them by
|
|
22
|
-
-- reporting a failure.
|
|
15
|
+
-- operations of python_pkg are built on. They are not part of the API.
|
|
23
16
|
|
|
24
17
|
library vunit_lib;
|
|
18
|
+
use vunit_lib.dict_pkg.all;
|
|
25
19
|
use vunit_lib.id_pkg.all;
|
|
26
20
|
use vunit_lib.integer_array_pkg.all;
|
|
27
21
|
use vunit_lib.integer_vector_ptr_pkg.all;
|
|
@@ -111,6 +105,9 @@ package python_ffi_pkg is
|
|
|
111
105
|
-----------------------------------------------------------------------------
|
|
112
106
|
-- Private, the primitives the bridge operations of python_pkg are built on
|
|
113
107
|
-----------------------------------------------------------------------------
|
|
108
|
+
-- Whether new_session has made a session with the identity
|
|
109
|
+
impure function p_has_session(id : id_t) return boolean;
|
|
110
|
+
|
|
114
111
|
-- Result kinds, must match src/vunit_python_bridge/runtime.py
|
|
115
112
|
constant p_kind_integer : integer := 0;
|
|
116
113
|
constant p_kind_real : integer := 1;
|
|
@@ -172,6 +169,7 @@ package python_ffi_pkg is
|
|
|
172
169
|
|
|
173
170
|
-- The result of the last evaluation
|
|
174
171
|
impure function p_result_integer return integer;
|
|
172
|
+
impure function p_result_real return real;
|
|
175
173
|
impure function p_result_string return string;
|
|
176
174
|
impure function p_result_integer_vector return integer_vector;
|
|
177
175
|
impure function p_result_real_vector return real_vector;
|
|
@@ -192,11 +190,20 @@ package body python_ffi_pkg is
|
|
|
192
190
|
return new_session(get_id(name, parent => p_python_id));
|
|
193
191
|
end;
|
|
194
192
|
|
|
193
|
+
-- The full names of the identities new_session has made sessions with
|
|
194
|
+
constant p_session_ids : dict_t := new_dict;
|
|
195
|
+
|
|
195
196
|
impure function new_session(id : id_t) return python_session_t is
|
|
196
197
|
begin
|
|
198
|
+
set_string(p_session_ids, full_name(id), "");
|
|
197
199
|
return (p_data => new_integer_vector_ptr(1, value => to_integer(id)));
|
|
198
200
|
end;
|
|
199
201
|
|
|
202
|
+
impure function p_has_session(id : id_t) return boolean is
|
|
203
|
+
begin
|
|
204
|
+
return has_key(p_session_ids, full_name(id));
|
|
205
|
+
end;
|
|
206
|
+
|
|
200
207
|
impure function get_id(session : python_session_t) return id_t is
|
|
201
208
|
begin
|
|
202
209
|
return to_id(get(session.p_data, 0));
|
|
@@ -338,6 +345,11 @@ package body python_ffi_pkg is
|
|
|
338
345
|
return vpy_result_integer;
|
|
339
346
|
end;
|
|
340
347
|
|
|
348
|
+
impure function p_result_real return real is
|
|
349
|
+
begin
|
|
350
|
+
return vpy_result_real;
|
|
351
|
+
end;
|
|
352
|
+
|
|
341
353
|
impure function p_result_string return string is
|
|
342
354
|
constant len : natural := vpy_result_meta(0);
|
|
343
355
|
variable result : string(1 to len);
|