vunit-python-bridge 0.1.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 +92 -0
- 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/bridge.py +171 -0
- vunit_python_bridge/foreign_application.py +90 -0
- vunit_python_bridge/hdl/src/python_bridge_pkg.vhd.in +91 -0
- vunit_python_bridge/hdl/src/python_context.vhd +13 -0
- vunit_python_bridge/hdl/src/python_ffi_pkg_bridge.vhd +507 -0
- vunit_python_bridge/hdl/src/python_pkg.vhd +1087 -0
- vunit_python_bridge/hdl/src/python_pkg_vhpi.vhd +270 -0
- vunit_python_bridge/hdl/tools/generate_python_pkg.py +386 -0
- vunit_python_bridge/hdl/tools/python_pkg.vhd.in +765 -0
- vunit_python_bridge/native/arguments.c +191 -0
- vunit_python_bridge/native/bridge.h +117 -0
- vunit_python_bridge/native/config.c +201 -0
- vunit_python_bridge/native/error.c +120 -0
- vunit_python_bridge/native/fli.c +98 -0
- vunit_python_bridge/native/interpreter.c +271 -0
- vunit_python_bridge/native/operations.c +239 -0
- vunit_python_bridge/native/vhpi/python_pkg.c +125 -0
- vunit_python_bridge/native/vhpi/python_pkg.h +31 -0
- vunit_python_bridge/native/vhpi/python_pkg_vhpi.c +366 -0
- vunit_python_bridge/native_library.py +455 -0
- vunit_python_bridge/runtime.py +645 -0
- vunit_python_bridge/simulator_hooks.py +141 -0
- vunit_python_bridge/vunit_pkg.toml +17 -0
- vunit_python_bridge-0.1.0.dist-info/METADATA +116 -0
- vunit_python_bridge-0.1.0.dist-info/RECORD +34 -0
- vunit_python_bridge-0.1.0.dist-info/WHEEL +5 -0
- vunit_python_bridge-0.1.0.dist-info/licenses/LICENSE +373 -0
- vunit_python_bridge-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,1087 @@
|
|
|
1
|
+
-- This package provides a dictionary types and operations
|
|
2
|
+
--
|
|
3
|
+
-- This Source Code Form is subject to the terms of the Mozilla Public
|
|
4
|
+
-- License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
|
5
|
+
-- You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
6
|
+
--
|
|
7
|
+
-- Copyright (c) 2014-2026, Lars Asplund lars.anders.asplund@gmail.com
|
|
8
|
+
|
|
9
|
+
use work.python_ffi_pkg.all;
|
|
10
|
+
library vunit_lib;
|
|
11
|
+
use vunit_lib.path.all;
|
|
12
|
+
use vunit_lib.run_pkg.all;
|
|
13
|
+
use vunit_lib.runner_pkg.all;
|
|
14
|
+
use vunit_lib.integer_vector_ptr_pkg.all;
|
|
15
|
+
use vunit_lib.string_ops.all;
|
|
16
|
+
|
|
17
|
+
use std.textio.all;
|
|
18
|
+
|
|
19
|
+
------------------------------------------------------------------------------
|
|
20
|
+
-- This file is generated from tools/python_pkg.vhd.in by
|
|
21
|
+
-- src/vunit_python_bridge/hdl/tools/generate_python_pkg.py. Do not edit.
|
|
22
|
+
library ieee;
|
|
23
|
+
use ieee.std_logic_1164.all;
|
|
24
|
+
use ieee.numeric_std.all;
|
|
25
|
+
|
|
26
|
+
use vunit_lib.integer_array_pkg.all;
|
|
27
|
+
use vunit_lib.logger_pkg.all;
|
|
28
|
+
------------------------------------------------------------------------------
|
|
29
|
+
|
|
30
|
+
package python_pkg is
|
|
31
|
+
procedure import_module_from_file(
|
|
32
|
+
module_path, as_module_name : string; session : python_session_t := default_session
|
|
33
|
+
);
|
|
34
|
+
procedure import_run_script(module_name : string := ""; session : python_session_t := default_session);
|
|
35
|
+
|
|
36
|
+
function to_py_list_str(vec : integer_vector) return string;
|
|
37
|
+
impure function to_py_list_str(vec : integer_vector_ptr_t) return string;
|
|
38
|
+
function to_py_list_str(vec : real_vector) return string;
|
|
39
|
+
|
|
40
|
+
function "+"(l, r : string) return string;
|
|
41
|
+
|
|
42
|
+
impure function eval_integer_vector_ptr(
|
|
43
|
+
expr : string; session : python_session_t := default_session
|
|
44
|
+
) return integer_vector_ptr_t;
|
|
45
|
+
alias eval is eval_integer_vector_ptr[string, python_session_t return integer_vector_ptr_t];
|
|
46
|
+
|
|
47
|
+
type arg_t is record
|
|
48
|
+
name : string;
|
|
49
|
+
value : string;
|
|
50
|
+
end record;
|
|
51
|
+
constant p_positional_arg : string := ".";
|
|
52
|
+
constant p_ignore_arg : string := "-";
|
|
53
|
+
constant p_group_arg : string := "*";
|
|
54
|
+
constant null_arg : arg_t := (name => p_ignore_arg, value => "");
|
|
55
|
+
|
|
56
|
+
function arg(value : integer) return arg_t;
|
|
57
|
+
function kwarg(kw : string; value : integer) return arg_t;
|
|
58
|
+
function arg(value : string) return arg_t;
|
|
59
|
+
function kwarg(kw : string; value : string) return arg_t;
|
|
60
|
+
function arg(value : integer_vector) return arg_t;
|
|
61
|
+
function kwarg(kw : string; value : integer_vector) return arg_t;
|
|
62
|
+
function arg(value : real) return arg_t;
|
|
63
|
+
function kwarg(kw : string; value : real) return arg_t;
|
|
64
|
+
function arg(value : boolean) return arg_t;
|
|
65
|
+
function kwarg(kw : string; value : boolean) return arg_t;
|
|
66
|
+
|
|
67
|
+
-- real_vector and integer_vector_ptr_t values become Python lists, a
|
|
68
|
+
-- std_ulogic value becomes True or False, and an unsigned or signed value of
|
|
69
|
+
-- any width becomes a Python integer written as a hexadecimal literal, which
|
|
70
|
+
-- is therefore not limited to the range of a VHDL integer.
|
|
71
|
+
--
|
|
72
|
+
-- An aggregate or a literal needs a qualified expression to select the
|
|
73
|
+
-- overload, for example arg(real_vector'(1.0, 2.0)). A std_ulogic_vector is
|
|
74
|
+
-- passed as a string, arg(to_string(slv)), or as a number,
|
|
75
|
+
-- arg_unsigned(unsigned(slv)). The unsigned and signed values have names of
|
|
76
|
+
-- their own since an overload would make a string literal argument,
|
|
77
|
+
-- arg("Hello"), ambiguous.
|
|
78
|
+
--
|
|
79
|
+
-- H and L are read as 1 and 0. Any other metavalue is an error.
|
|
80
|
+
--
|
|
81
|
+
-- An integer_array_t value is transferred to Python by the Python bridge,
|
|
82
|
+
-- which is only available for NVC, GHDL and Questa, and is referred to by
|
|
83
|
+
-- the expression, which means that it can be used in several calls.
|
|
84
|
+
function arg(value : real_vector) return arg_t;
|
|
85
|
+
function kwarg(kw : string; value : real_vector) return arg_t;
|
|
86
|
+
impure function arg(value : integer_vector_ptr_t) return arg_t;
|
|
87
|
+
impure function kwarg(kw : string; value : integer_vector_ptr_t) return arg_t;
|
|
88
|
+
impure function arg(value : std_ulogic) return arg_t;
|
|
89
|
+
impure function kwarg(kw : string; value : std_ulogic) return arg_t;
|
|
90
|
+
impure function arg_unsigned(value : unsigned) return arg_t;
|
|
91
|
+
impure function kwarg_unsigned(kw : string; value : unsigned) return arg_t;
|
|
92
|
+
impure function arg_signed(value : signed) return arg_t;
|
|
93
|
+
impure function kwarg_signed(kw : string; value : signed) return arg_t;
|
|
94
|
+
impure function arg(value : integer_array_t) return arg_t;
|
|
95
|
+
impure function kwarg(kw : string; value : integer_array_t) return arg_t;
|
|
96
|
+
|
|
97
|
+
-- The Python expression calling identifier with the given arguments, for
|
|
98
|
+
-- example to embed a call in a larger exec or eval string:
|
|
99
|
+
--
|
|
100
|
+
-- exec("gcd = " & to_call_str("gcd", arg(35), arg(77)));
|
|
101
|
+
impure function to_call_str(
|
|
102
|
+
identifier : string; arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10 : arg_t := null_arg
|
|
103
|
+
) return string;
|
|
104
|
+
|
|
105
|
+
impure function call_integer_w_arg(
|
|
106
|
+
identifier : string; arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10 : arg_t := null_arg;
|
|
107
|
+
session : python_session_t := default_session
|
|
108
|
+
) return integer;
|
|
109
|
+
alias call is call_integer_w_arg[
|
|
110
|
+
string, arg_t, arg_t, arg_t, arg_t, arg_t, arg_t, arg_t, arg_t, arg_t, arg_t, python_session_t return integer];
|
|
111
|
+
|
|
112
|
+
procedure call(
|
|
113
|
+
identifier : string; arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10 : arg_t := null_arg;
|
|
114
|
+
session : python_session_t := default_session
|
|
115
|
+
);
|
|
116
|
+
|
|
117
|
+
impure function call_integer_vector(
|
|
118
|
+
identifier : string; arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10 : arg_t := null_arg;
|
|
119
|
+
session : python_session_t := default_session
|
|
120
|
+
) return integer_vector;
|
|
121
|
+
alias call is call_integer_vector[
|
|
122
|
+
string, arg_t, arg_t, arg_t, arg_t, arg_t, arg_t, arg_t, arg_t, arg_t, arg_t, python_session_t
|
|
123
|
+
return integer_vector];
|
|
124
|
+
|
|
125
|
+
impure function call_real(
|
|
126
|
+
identifier : string; arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10 : arg_t := null_arg;
|
|
127
|
+
session : python_session_t := default_session
|
|
128
|
+
) return real;
|
|
129
|
+
alias call is call_real[
|
|
130
|
+
string, arg_t, arg_t, arg_t, arg_t, arg_t, arg_t, arg_t, arg_t, arg_t, arg_t, python_session_t return real];
|
|
131
|
+
|
|
132
|
+
-----------------------------------------------------------------------------
|
|
133
|
+
-- Argument groups
|
|
134
|
+
-----------------------------------------------------------------------------
|
|
135
|
+
-- Arguments combined with & become a single argument, so that a call can
|
|
136
|
+
-- pass more than the 10 arguments it takes and can build its arguments in
|
|
137
|
+
-- steps:
|
|
138
|
+
--
|
|
139
|
+
-- call("f", arg(x), kwarg("a", 1) & kwarg("b", 2));
|
|
140
|
+
--
|
|
141
|
+
-- calls f(x, **dict(a=1, b=2)). A group of positional arguments becomes
|
|
142
|
+
-- *(1, 2,) and a group with both kinds *(1,), **dict(a=1). Python keeps its
|
|
143
|
+
-- own rules: a repeated keyword within a group is a syntax error and so is a
|
|
144
|
+
-- group followed by a positional argument of the call. Appending a
|
|
145
|
+
-- positional argument to a group that already has keyword arguments is an
|
|
146
|
+
-- error for the same reason.
|
|
147
|
+
--
|
|
148
|
+
-- null_arg is the identity of the operation, which is what makes a group
|
|
149
|
+
-- possible to build one argument at a time, ending with null_arg, and what
|
|
150
|
+
-- lets a helper that contributes an optional argument return null_arg when
|
|
151
|
+
-- it has none. An empty group is a valid call with no arguments rather than
|
|
152
|
+
-- an error.
|
|
153
|
+
impure function "&"(l, r : arg_t) return arg_t;
|
|
154
|
+
|
|
155
|
+
-----------------------------------------------------------------------------
|
|
156
|
+
-- Operations implemented by the Python bridge (NVC, GHDL and Questa)
|
|
157
|
+
-----------------------------------------------------------------------------
|
|
158
|
+
-- The operations below are implemented by the VUnit Python bridge and are
|
|
159
|
+
-- therefore only available for NVC, GHDL and Questa; the other simulators
|
|
160
|
+
-- report a failure when they are used. Like the other operations, every one
|
|
161
|
+
-- of them takes the session it is performed in as its last parameter,
|
|
162
|
+
-- defaulting to the default session.
|
|
163
|
+
|
|
164
|
+
-----------------------------------------------------------------------------
|
|
165
|
+
-- Results of eval: boolean, std_ulogic, vectors and arrays
|
|
166
|
+
-----------------------------------------------------------------------------
|
|
167
|
+
-- std_ulogic_vector and integer_array_t results are only available under
|
|
168
|
+
-- their explicit names, not as eval overloads, which keeps
|
|
169
|
+
-- check_equal(eval("17"), 17) and length(eval("[1, 2]")) unambiguous.
|
|
170
|
+
-- signed and unsigned results are only available in the procedure form
|
|
171
|
+
-- since a function cannot know the width of the result.
|
|
172
|
+
impure function eval_boolean(
|
|
173
|
+
expr : string; session : python_session_t := default_session
|
|
174
|
+
) return boolean;
|
|
175
|
+
alias eval is eval_boolean[string, python_session_t return boolean];
|
|
176
|
+
|
|
177
|
+
impure function eval_std_ulogic(
|
|
178
|
+
expr : string; session : python_session_t := default_session
|
|
179
|
+
) return std_ulogic;
|
|
180
|
+
alias eval is eval_std_ulogic[string, python_session_t return std_ulogic];
|
|
181
|
+
|
|
182
|
+
impure function eval_std_ulogic_vector(
|
|
183
|
+
expr : string; session : python_session_t := default_session
|
|
184
|
+
) return std_ulogic_vector;
|
|
185
|
+
|
|
186
|
+
impure function eval_integer_array(
|
|
187
|
+
expr : string; session : python_session_t := default_session
|
|
188
|
+
) return integer_array_t;
|
|
189
|
+
|
|
190
|
+
procedure eval_std_ulogic_vector(
|
|
191
|
+
expr : string; result : out std_ulogic_vector; session : python_session_t := default_session
|
|
192
|
+
);
|
|
193
|
+
procedure eval_signed(
|
|
194
|
+
expr : string; result : out signed; session : python_session_t := default_session
|
|
195
|
+
);
|
|
196
|
+
procedure eval_unsigned(
|
|
197
|
+
expr : string; result : out unsigned; session : python_session_t := default_session
|
|
198
|
+
);
|
|
199
|
+
|
|
200
|
+
-----------------------------------------------------------------------------
|
|
201
|
+
-- Results of call: string, boolean, std_ulogic, vectors and arrays
|
|
202
|
+
-----------------------------------------------------------------------------
|
|
203
|
+
impure function call_real_vector(
|
|
204
|
+
identifier : string; arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10 : arg_t := null_arg;
|
|
205
|
+
session : python_session_t := default_session
|
|
206
|
+
) return real_vector;
|
|
207
|
+
alias call is call_real_vector[
|
|
208
|
+
string, arg_t, arg_t, arg_t, arg_t, arg_t, arg_t, arg_t, arg_t, arg_t, arg_t, python_session_t return real_vector];
|
|
209
|
+
|
|
210
|
+
impure function call_string(
|
|
211
|
+
identifier : string; arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10 : arg_t := null_arg;
|
|
212
|
+
session : python_session_t := default_session
|
|
213
|
+
) return string;
|
|
214
|
+
alias call is call_string[
|
|
215
|
+
string, arg_t, arg_t, arg_t, arg_t, arg_t, arg_t, arg_t, arg_t, arg_t, arg_t, python_session_t return string];
|
|
216
|
+
|
|
217
|
+
impure function call_integer_vector_ptr(
|
|
218
|
+
identifier : string; arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10 : arg_t := null_arg;
|
|
219
|
+
session : python_session_t := default_session
|
|
220
|
+
) return integer_vector_ptr_t;
|
|
221
|
+
alias call is call_integer_vector_ptr[
|
|
222
|
+
string, arg_t, arg_t, arg_t, arg_t, arg_t, arg_t, arg_t, arg_t, arg_t, arg_t, python_session_t return integer_vector_ptr_t];
|
|
223
|
+
|
|
224
|
+
impure function call_boolean(
|
|
225
|
+
identifier : string; arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10 : arg_t := null_arg;
|
|
226
|
+
session : python_session_t := default_session
|
|
227
|
+
) return boolean;
|
|
228
|
+
alias call is call_boolean[
|
|
229
|
+
string, arg_t, arg_t, arg_t, arg_t, arg_t, arg_t, arg_t, arg_t, arg_t, arg_t, python_session_t return boolean];
|
|
230
|
+
|
|
231
|
+
impure function call_std_ulogic(
|
|
232
|
+
identifier : string; arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10 : arg_t := null_arg;
|
|
233
|
+
session : python_session_t := default_session
|
|
234
|
+
) return std_ulogic;
|
|
235
|
+
alias call is call_std_ulogic[
|
|
236
|
+
string, arg_t, arg_t, arg_t, arg_t, arg_t, arg_t, arg_t, arg_t, arg_t, arg_t, python_session_t return std_ulogic];
|
|
237
|
+
|
|
238
|
+
impure function call_std_ulogic_vector(
|
|
239
|
+
identifier : string; arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10 : arg_t := null_arg;
|
|
240
|
+
session : python_session_t := default_session
|
|
241
|
+
) return std_ulogic_vector;
|
|
242
|
+
|
|
243
|
+
impure function call_integer_array(
|
|
244
|
+
identifier : string; arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10 : arg_t := null_arg;
|
|
245
|
+
session : python_session_t := default_session
|
|
246
|
+
) return integer_array_t;
|
|
247
|
+
alias call is call_integer_array[
|
|
248
|
+
string, arg_t, arg_t, arg_t, arg_t, arg_t, arg_t, arg_t, arg_t, arg_t, arg_t, python_session_t return integer_array_t];
|
|
249
|
+
|
|
250
|
+
procedure call_std_ulogic_vector(
|
|
251
|
+
identifier : string; result : out std_ulogic_vector;
|
|
252
|
+
arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10 : arg_t := null_arg;
|
|
253
|
+
session : python_session_t := default_session
|
|
254
|
+
);
|
|
255
|
+
procedure call_signed(
|
|
256
|
+
identifier : string; result : out signed;
|
|
257
|
+
arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10 : arg_t := null_arg;
|
|
258
|
+
session : python_session_t := default_session
|
|
259
|
+
);
|
|
260
|
+
procedure call_unsigned(
|
|
261
|
+
identifier : string; result : out unsigned;
|
|
262
|
+
arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10 : arg_t := null_arg;
|
|
263
|
+
session : python_session_t := default_session
|
|
264
|
+
);
|
|
265
|
+
|
|
266
|
+
-----------------------------------------------------------------------------
|
|
267
|
+
-- Execution of Python files
|
|
268
|
+
-----------------------------------------------------------------------------
|
|
269
|
+
-- Execute a Python file. A relative file name is relative to the directory
|
|
270
|
+
-- of the testbench file, tb_path, and an absolute file name is used as it
|
|
271
|
+
-- is given. The file is executed with __file__ set and its own directory on
|
|
272
|
+
-- sys.path so that it can import its siblings.
|
|
273
|
+
procedure exec_file(file_name : string; session : python_session_t := default_session);
|
|
274
|
+
end package;
|
|
275
|
+
|
|
276
|
+
package body python_pkg is
|
|
277
|
+
-- @formatter:off
|
|
278
|
+
procedure import_module_from_file(
|
|
279
|
+
module_path, as_module_name : string; session : python_session_t := default_session
|
|
280
|
+
) is
|
|
281
|
+
constant spec_name : string := "__" & as_module_name & "_spec";
|
|
282
|
+
constant code : string :=
|
|
283
|
+
"from importlib.util import spec_from_file_location, module_from_spec" & LF &
|
|
284
|
+
"from pathlib import Path" & LF &
|
|
285
|
+
"import sys" & LF &
|
|
286
|
+
spec_name & " = spec_from_file_location('" & as_module_name & "', str(Path('" & module_path & "')))" & LF &
|
|
287
|
+
as_module_name & " = module_from_spec(" & spec_name & ")" & LF &
|
|
288
|
+
"sys.modules['" & as_module_name & "'] = " & as_module_name & LF &
|
|
289
|
+
spec_name & ".loader.exec_module(" & as_module_name & ")";
|
|
290
|
+
begin
|
|
291
|
+
exec(code, session);
|
|
292
|
+
end;
|
|
293
|
+
-- @formatter:on
|
|
294
|
+
|
|
295
|
+
-- Importing a run script runs its module level code, so one without an
|
|
296
|
+
-- if __name__ == "__main__" guard would start VUnit again
|
|
297
|
+
procedure p_check_run_script_guard(script_path : string; session : python_session_t) is
|
|
298
|
+
begin
|
|
299
|
+
exec(
|
|
300
|
+
"from pathlib import Path" & LF &
|
|
301
|
+
"if '__main__' not in Path('" & script_path & "').read_text():" & LF &
|
|
302
|
+
" raise RuntimeError('The run script " & script_path & " has no if __name__ == ""__main__"" guard, " &
|
|
303
|
+
"importing it would run VUnit again')",
|
|
304
|
+
session);
|
|
305
|
+
end;
|
|
306
|
+
|
|
307
|
+
procedure import_run_script(module_name : string := ""; session : python_session_t := default_session) is
|
|
308
|
+
constant script_path : string := run_script_path(get_cfg(runner_state));
|
|
309
|
+
variable path_items : lines_t;
|
|
310
|
+
variable script_name : line;
|
|
311
|
+
begin
|
|
312
|
+
if script_path = "" then
|
|
313
|
+
exec("raise RuntimeError('import_run_script: VUnit was not started from a run script file')", session);
|
|
314
|
+
return;
|
|
315
|
+
end if;
|
|
316
|
+
p_check_run_script_guard(script_path, session);
|
|
317
|
+
if module_name = "" then
|
|
318
|
+
-- Extract the last item in the full path
|
|
319
|
+
path_items := split(script_path, "/");
|
|
320
|
+
for idx in path_items'range loop
|
|
321
|
+
if idx = path_items'right then
|
|
322
|
+
script_name := path_items(idx);
|
|
323
|
+
else
|
|
324
|
+
deallocate(path_items(idx));
|
|
325
|
+
end if;
|
|
326
|
+
end loop;
|
|
327
|
+
deallocate(path_items);
|
|
328
|
+
|
|
329
|
+
-- Set module name to script name minus its extension
|
|
330
|
+
path_items := split(script_name.all, ".");
|
|
331
|
+
deallocate(script_name);
|
|
332
|
+
for idx in path_items'range loop
|
|
333
|
+
if idx = path_items'left then
|
|
334
|
+
import_module_from_file(script_path, path_items(idx).all, session);
|
|
335
|
+
end if;
|
|
336
|
+
deallocate(path_items(idx));
|
|
337
|
+
end loop;
|
|
338
|
+
deallocate(path_items);
|
|
339
|
+
else
|
|
340
|
+
import_module_from_file(script_path, module_name, session);
|
|
341
|
+
end if;
|
|
342
|
+
end;
|
|
343
|
+
|
|
344
|
+
function to_py_list_str(vec : integer_vector) return string is
|
|
345
|
+
variable l : line;
|
|
346
|
+
begin
|
|
347
|
+
swrite(l, "[");
|
|
348
|
+
for idx in vec'range loop
|
|
349
|
+
swrite(l, to_string(vec(idx)));
|
|
350
|
+
if idx /= vec'right then
|
|
351
|
+
swrite(l, ",");
|
|
352
|
+
end if;
|
|
353
|
+
end loop;
|
|
354
|
+
swrite(l, "]");
|
|
355
|
+
|
|
356
|
+
return l.all;
|
|
357
|
+
end;
|
|
358
|
+
|
|
359
|
+
impure function to_py_list_str(vec : integer_vector_ptr_t) return string is
|
|
360
|
+
variable l : line;
|
|
361
|
+
begin
|
|
362
|
+
swrite(l, "[");
|
|
363
|
+
for idx in 0 to length(vec) - 1 loop
|
|
364
|
+
swrite(l, to_string(get(vec, idx)));
|
|
365
|
+
if idx /= length(vec) - 1 then
|
|
366
|
+
swrite(l, ",");
|
|
367
|
+
end if;
|
|
368
|
+
end loop;
|
|
369
|
+
swrite(l, "]");
|
|
370
|
+
|
|
371
|
+
return l.all;
|
|
372
|
+
end;
|
|
373
|
+
|
|
374
|
+
function to_py_list_str(vec : real_vector) return string is
|
|
375
|
+
variable l : line;
|
|
376
|
+
begin
|
|
377
|
+
swrite(l, "[");
|
|
378
|
+
for idx in vec'range loop
|
|
379
|
+
-- Use %.16e to ensure that the string representation of the real number is precise enough to avoid loss of
|
|
380
|
+
-- information when double-precision is used.
|
|
381
|
+
swrite(l, to_string(vec(idx), "%.16e"));
|
|
382
|
+
if idx /= vec'right then
|
|
383
|
+
swrite(l, ",");
|
|
384
|
+
end if;
|
|
385
|
+
end loop;
|
|
386
|
+
swrite(l, "]");
|
|
387
|
+
|
|
388
|
+
return l.all;
|
|
389
|
+
end;
|
|
390
|
+
|
|
391
|
+
function "+"(l, r : string) return string is
|
|
392
|
+
begin
|
|
393
|
+
return l & LF & r;
|
|
394
|
+
end;
|
|
395
|
+
|
|
396
|
+
impure function eval_integer_vector_ptr(
|
|
397
|
+
expr : string; session : python_session_t := default_session
|
|
398
|
+
) return integer_vector_ptr_t is
|
|
399
|
+
constant result_integer_vector : integer_vector := eval(expr, session);
|
|
400
|
+
constant len : natural := result_integer_vector'length;
|
|
401
|
+
constant result_integer_vector_normalized : integer_vector(0 to len - 1) := result_integer_vector;
|
|
402
|
+
constant result : integer_vector_ptr_t := new_integer_vector_ptr(len);
|
|
403
|
+
begin
|
|
404
|
+
for idx in 0 to len - 1 loop
|
|
405
|
+
set(result, idx, result_integer_vector_normalized(idx));
|
|
406
|
+
end loop;
|
|
407
|
+
|
|
408
|
+
return result;
|
|
409
|
+
end;
|
|
410
|
+
|
|
411
|
+
function arg(value : integer) return arg_t is
|
|
412
|
+
begin
|
|
413
|
+
return (p_positional_arg, to_string(value));
|
|
414
|
+
end;
|
|
415
|
+
|
|
416
|
+
function kwarg(kw : string; value : integer) return arg_t is
|
|
417
|
+
begin
|
|
418
|
+
return (kw, to_string(value));
|
|
419
|
+
end;
|
|
420
|
+
|
|
421
|
+
function arg(value : string) return arg_t is
|
|
422
|
+
begin
|
|
423
|
+
return (p_positional_arg, '"' & value & '"');
|
|
424
|
+
end;
|
|
425
|
+
|
|
426
|
+
function kwarg(kw : string; value : string) return arg_t is
|
|
427
|
+
begin
|
|
428
|
+
return (kw, '"' & value & '"');
|
|
429
|
+
end;
|
|
430
|
+
|
|
431
|
+
function arg(value : integer_vector) return arg_t is
|
|
432
|
+
begin
|
|
433
|
+
return (p_positional_arg, to_py_list_str(value));
|
|
434
|
+
end;
|
|
435
|
+
|
|
436
|
+
function kwarg(kw : string; value : integer_vector) return arg_t is
|
|
437
|
+
begin
|
|
438
|
+
return (kw, to_py_list_str(value));
|
|
439
|
+
end;
|
|
440
|
+
|
|
441
|
+
function arg(value : real) return arg_t is
|
|
442
|
+
begin
|
|
443
|
+
return (p_positional_arg, to_string(value, "%.16e"));
|
|
444
|
+
end;
|
|
445
|
+
|
|
446
|
+
function kwarg(kw : string; value : real) return arg_t is
|
|
447
|
+
begin
|
|
448
|
+
return (kw, to_string(value, "%.16e"));
|
|
449
|
+
end;
|
|
450
|
+
|
|
451
|
+
function arg(value : boolean) return arg_t is
|
|
452
|
+
begin
|
|
453
|
+
if value then
|
|
454
|
+
return (p_positional_arg, "True");
|
|
455
|
+
else
|
|
456
|
+
return (p_positional_arg, "False");
|
|
457
|
+
end if;
|
|
458
|
+
end;
|
|
459
|
+
|
|
460
|
+
function kwarg(kw : string; value : boolean) return arg_t is
|
|
461
|
+
begin
|
|
462
|
+
if value then
|
|
463
|
+
return (kw, "True");
|
|
464
|
+
else
|
|
465
|
+
return (kw, "False");
|
|
466
|
+
end if;
|
|
467
|
+
end;
|
|
468
|
+
|
|
469
|
+
-- The Python source text of a message, escaped for a double quoted Python
|
|
470
|
+
-- string. A quote, a backslash and a line break are the characters that
|
|
471
|
+
-- cannot be written as they are.
|
|
472
|
+
function p_quoted(message : string) return string is
|
|
473
|
+
variable result : line;
|
|
474
|
+
begin
|
|
475
|
+
swrite(result, """");
|
|
476
|
+
for idx in message'range loop
|
|
477
|
+
case message(idx) is
|
|
478
|
+
when '"' | '\' => swrite(result, "\" & message(idx));
|
|
479
|
+
when LF => swrite(result, "\n");
|
|
480
|
+
when CR => swrite(result, "\r");
|
|
481
|
+
when others => swrite(result, string'(1 => message(idx)));
|
|
482
|
+
end case;
|
|
483
|
+
end loop;
|
|
484
|
+
swrite(result, """");
|
|
485
|
+
|
|
486
|
+
return result.all;
|
|
487
|
+
end;
|
|
488
|
+
|
|
489
|
+
-- Report a value that could not be converted and give it a Python source
|
|
490
|
+
-- text raising the same message, so that the call the argument is used in
|
|
491
|
+
-- fails the same way rather than being made without the argument.
|
|
492
|
+
impure function p_failed_value(message : string) return string is
|
|
493
|
+
begin
|
|
494
|
+
failure(python_logger, message);
|
|
495
|
+
return "__vunit__.error(" & p_quoted(message) & ")";
|
|
496
|
+
end;
|
|
497
|
+
|
|
498
|
+
-- The Python source text of an argument value. The overloads whose
|
|
499
|
+
-- conversion can fail take the name of the operation, used to report a value
|
|
500
|
+
-- that cannot be converted.
|
|
501
|
+
function p_arg_value(value : real_vector) return string is
|
|
502
|
+
begin
|
|
503
|
+
return to_py_list_str(value);
|
|
504
|
+
end;
|
|
505
|
+
|
|
506
|
+
impure function p_arg_value(value : integer_vector_ptr_t) return string is
|
|
507
|
+
begin
|
|
508
|
+
return to_py_list_str(value);
|
|
509
|
+
end;
|
|
510
|
+
|
|
511
|
+
impure function p_arg_value(value : std_ulogic; operation : string) return string is
|
|
512
|
+
begin
|
|
513
|
+
if to_x01(value) = '1' then
|
|
514
|
+
return "True";
|
|
515
|
+
elsif to_x01(value) = '0' then
|
|
516
|
+
return "False";
|
|
517
|
+
end if;
|
|
518
|
+
return p_failed_value(
|
|
519
|
+
operation & " cannot convert " & std_ulogic'image(value) & "; expected '0', '1', 'L' or 'H'"
|
|
520
|
+
);
|
|
521
|
+
end;
|
|
522
|
+
|
|
523
|
+
-- The Python hexadecimal literal of the magnitude given by the bits, for
|
|
524
|
+
-- example 0x1F or -0x80. A null range gives 0x0.
|
|
525
|
+
function p_to_hex_literal(bits : std_ulogic_vector; negative : boolean) return string is
|
|
526
|
+
constant hex_digits : string(1 to 16) := "0123456789ABCDEF";
|
|
527
|
+
constant padding : natural := (4 - bits'length mod 4) mod 4;
|
|
528
|
+
variable padded : std_ulogic_vector(bits'length + padding - 1 downto 0) := (others => '0');
|
|
529
|
+
variable result : line;
|
|
530
|
+
variable digit : natural;
|
|
531
|
+
variable leading : boolean := true;
|
|
532
|
+
begin
|
|
533
|
+
padded(bits'length - 1 downto 0) := bits;
|
|
534
|
+
swrite(result, "0x");
|
|
535
|
+
for nibble in padded'length / 4 - 1 downto 0 loop
|
|
536
|
+
digit := 0;
|
|
537
|
+
for idx in 3 downto 0 loop
|
|
538
|
+
digit := 2 * digit;
|
|
539
|
+
if padded(4 * nibble + idx) = '1' then
|
|
540
|
+
digit := digit + 1;
|
|
541
|
+
end if;
|
|
542
|
+
end loop;
|
|
543
|
+
if digit /= 0 then
|
|
544
|
+
leading := false;
|
|
545
|
+
end if;
|
|
546
|
+
if not leading then
|
|
547
|
+
swrite(result, string'(1 => hex_digits(digit + 1)));
|
|
548
|
+
end if;
|
|
549
|
+
end loop;
|
|
550
|
+
if leading then
|
|
551
|
+
swrite(result, "0");
|
|
552
|
+
end if;
|
|
553
|
+
|
|
554
|
+
if negative then
|
|
555
|
+
return "-" & result.all;
|
|
556
|
+
end if;
|
|
557
|
+
return result.all;
|
|
558
|
+
end;
|
|
559
|
+
|
|
560
|
+
-- The error reported for a vector value that cannot be converted
|
|
561
|
+
function p_metavalue_error(value : std_ulogic_vector; operation : string) return string is
|
|
562
|
+
begin
|
|
563
|
+
return operation & " cannot convert """ & to_string(value) & """; the value has metavalues";
|
|
564
|
+
end;
|
|
565
|
+
|
|
566
|
+
impure function p_arg_value(value : unsigned; operation : string) return string is
|
|
567
|
+
begin
|
|
568
|
+
if is_x(std_ulogic_vector(value)) then
|
|
569
|
+
return p_failed_value(p_metavalue_error(std_ulogic_vector(value), operation));
|
|
570
|
+
end if;
|
|
571
|
+
return p_to_hex_literal(to_x01(std_ulogic_vector(value)), false);
|
|
572
|
+
end;
|
|
573
|
+
|
|
574
|
+
impure function p_arg_value(value : signed; operation : string) return string is
|
|
575
|
+
variable folded : signed(value'length - 1 downto 0);
|
|
576
|
+
variable magnitude : signed(value'length downto 0);
|
|
577
|
+
begin
|
|
578
|
+
if is_x(std_ulogic_vector(value)) then
|
|
579
|
+
return p_failed_value(p_metavalue_error(std_ulogic_vector(value), operation));
|
|
580
|
+
end if;
|
|
581
|
+
if value'length = 0 then
|
|
582
|
+
return "0x0";
|
|
583
|
+
end if;
|
|
584
|
+
|
|
585
|
+
folded := signed(to_x01(std_ulogic_vector(value)));
|
|
586
|
+
if folded(folded'left) = '0' then
|
|
587
|
+
return p_to_hex_literal(std_ulogic_vector(folded), false);
|
|
588
|
+
end if;
|
|
589
|
+
-- Resizing before negating keeps the magnitude of signed'low representable
|
|
590
|
+
magnitude := -resize(folded, value'length + 1);
|
|
591
|
+
return p_to_hex_literal(std_ulogic_vector(magnitude), true);
|
|
592
|
+
end;
|
|
593
|
+
|
|
594
|
+
impure function p_arg_value(value : integer_array_t; operation : string) return string is
|
|
595
|
+
constant staged_id : integer := p_stage_array(value, operation);
|
|
596
|
+
begin
|
|
597
|
+
if staged_id < 1 then
|
|
598
|
+
-- p_stage_array reported the error of the transfer
|
|
599
|
+
return "__vunit__.error(" & p_quoted(operation & " failed") & ")";
|
|
600
|
+
end if;
|
|
601
|
+
return "__vunit__.staged(" & integer'image(staged_id) & ")";
|
|
602
|
+
end;
|
|
603
|
+
|
|
604
|
+
function arg(value : real_vector) return arg_t is
|
|
605
|
+
begin
|
|
606
|
+
return (p_positional_arg, p_arg_value(value));
|
|
607
|
+
end;
|
|
608
|
+
|
|
609
|
+
function kwarg(kw : string; value : real_vector) return arg_t is
|
|
610
|
+
begin
|
|
611
|
+
return (kw, p_arg_value(value));
|
|
612
|
+
end;
|
|
613
|
+
|
|
614
|
+
impure function arg(value : integer_vector_ptr_t) return arg_t is
|
|
615
|
+
begin
|
|
616
|
+
return (p_positional_arg, p_arg_value(value));
|
|
617
|
+
end;
|
|
618
|
+
|
|
619
|
+
impure function kwarg(kw : string; value : integer_vector_ptr_t) return arg_t is
|
|
620
|
+
begin
|
|
621
|
+
return (kw, p_arg_value(value));
|
|
622
|
+
end;
|
|
623
|
+
|
|
624
|
+
impure function arg(value : std_ulogic) return arg_t is
|
|
625
|
+
begin
|
|
626
|
+
return (p_positional_arg, p_arg_value(value, "arg"));
|
|
627
|
+
end;
|
|
628
|
+
|
|
629
|
+
impure function kwarg(kw : string; value : std_ulogic) return arg_t is
|
|
630
|
+
begin
|
|
631
|
+
return (kw, p_arg_value(value, "kwarg"));
|
|
632
|
+
end;
|
|
633
|
+
|
|
634
|
+
impure function arg_unsigned(value : unsigned) return arg_t is
|
|
635
|
+
begin
|
|
636
|
+
return (p_positional_arg, p_arg_value(value, "arg_unsigned"));
|
|
637
|
+
end;
|
|
638
|
+
|
|
639
|
+
impure function kwarg_unsigned(kw : string; value : unsigned) return arg_t is
|
|
640
|
+
begin
|
|
641
|
+
return (kw, p_arg_value(value, "kwarg_unsigned"));
|
|
642
|
+
end;
|
|
643
|
+
|
|
644
|
+
impure function arg_signed(value : signed) return arg_t is
|
|
645
|
+
begin
|
|
646
|
+
return (p_positional_arg, p_arg_value(value, "arg_signed"));
|
|
647
|
+
end;
|
|
648
|
+
|
|
649
|
+
impure function kwarg_signed(kw : string; value : signed) return arg_t is
|
|
650
|
+
begin
|
|
651
|
+
return (kw, p_arg_value(value, "kwarg_signed"));
|
|
652
|
+
end;
|
|
653
|
+
|
|
654
|
+
impure function arg(value : integer_array_t) return arg_t is
|
|
655
|
+
begin
|
|
656
|
+
return (p_positional_arg, p_arg_value(value, "arg"));
|
|
657
|
+
end;
|
|
658
|
+
|
|
659
|
+
impure function kwarg(kw : string; value : integer_array_t) return arg_t is
|
|
660
|
+
begin
|
|
661
|
+
return (kw, p_arg_value(value, "kwarg"));
|
|
662
|
+
end;
|
|
663
|
+
|
|
664
|
+
-----------------------------------------------------------------------------
|
|
665
|
+
-- Argument groups
|
|
666
|
+
-----------------------------------------------------------------------------
|
|
667
|
+
-- A group is one argument whose Python source text is spliced into the call
|
|
668
|
+
-- like a positional argument: *(1, 2,) for positional arguments,
|
|
669
|
+
-- **dict(a=1, b=2) for keyword arguments and *(1,), **dict(a=1) for both.
|
|
670
|
+
-- Its name is the group marker followed by the length of the positional
|
|
671
|
+
-- part, which is what tells the two parts apart when more arguments are
|
|
672
|
+
-- appended to the group.
|
|
673
|
+
constant p_positional_group : string := "*(";
|
|
674
|
+
constant p_keyword_group : string := "**dict(";
|
|
675
|
+
|
|
676
|
+
function p_is_group(value : arg_t) return boolean is
|
|
677
|
+
alias name : string(1 to value.name'length) is value.name;
|
|
678
|
+
begin
|
|
679
|
+
if name'length <= p_group_arg'length then
|
|
680
|
+
return false;
|
|
681
|
+
end if;
|
|
682
|
+
return name(1 to p_group_arg'length) = p_group_arg;
|
|
683
|
+
end;
|
|
684
|
+
|
|
685
|
+
-- The length of the positional part of a group, 0 when it has none
|
|
686
|
+
function p_group_split(value : arg_t) return natural is
|
|
687
|
+
alias name : string(1 to value.name'length) is value.name;
|
|
688
|
+
begin
|
|
689
|
+
return natural'value(name(p_group_arg'length + 1 to name'length));
|
|
690
|
+
end;
|
|
691
|
+
|
|
692
|
+
-- The positional arguments of an operand as they are written within *(...).
|
|
693
|
+
-- Every argument is followed by a comma, which is what makes *(1,) a tuple.
|
|
694
|
+
function p_positional_items(value : arg_t) return string is
|
|
695
|
+
alias text : string(1 to value.value'length) is value.value;
|
|
696
|
+
begin
|
|
697
|
+
if value.name = p_positional_arg then
|
|
698
|
+
return text & ",";
|
|
699
|
+
elsif p_is_group(value) then
|
|
700
|
+
if p_group_split(value) = 0 then
|
|
701
|
+
return "";
|
|
702
|
+
end if;
|
|
703
|
+
-- Drop the *( prefix and the ) of the positional part
|
|
704
|
+
return text(p_positional_group'length + 1 to p_group_split(value) - 1);
|
|
705
|
+
end if;
|
|
706
|
+
return "";
|
|
707
|
+
end;
|
|
708
|
+
|
|
709
|
+
-- The keyword arguments of an operand as they are written within **dict(...)
|
|
710
|
+
function p_keyword_items(value : arg_t) return string is
|
|
711
|
+
alias text : string(1 to value.value'length) is value.value;
|
|
712
|
+
begin
|
|
713
|
+
if value.name = p_ignore_arg or value.name = p_positional_arg then
|
|
714
|
+
return "";
|
|
715
|
+
elsif not p_is_group(value) then
|
|
716
|
+
return value.name & "=" & value.value;
|
|
717
|
+
elsif p_group_split(value) = text'length then
|
|
718
|
+
return "";
|
|
719
|
+
elsif p_group_split(value) = 0 then
|
|
720
|
+
-- Keyword arguments only: drop the **dict( prefix and the trailing )
|
|
721
|
+
return text(p_keyword_group'length + 1 to text'length - 1);
|
|
722
|
+
end if;
|
|
723
|
+
-- Both kinds: the keyword part follows the positional part and ", "
|
|
724
|
+
return text(p_group_split(value) + 2 + p_keyword_group'length + 1 to text'length - 1);
|
|
725
|
+
end;
|
|
726
|
+
|
|
727
|
+
-- The arguments of both operands, separated
|
|
728
|
+
function p_join(l, r, separator : string) return string is
|
|
729
|
+
begin
|
|
730
|
+
if l = "" then
|
|
731
|
+
return r;
|
|
732
|
+
elsif r = "" then
|
|
733
|
+
return l;
|
|
734
|
+
end if;
|
|
735
|
+
return l & separator & r;
|
|
736
|
+
end;
|
|
737
|
+
|
|
738
|
+
-- *(...) or **dict(...) of the arguments, nothing when there are none
|
|
739
|
+
function p_group_text(prefix, items : string) return string is
|
|
740
|
+
begin
|
|
741
|
+
if items = "" then
|
|
742
|
+
return "";
|
|
743
|
+
end if;
|
|
744
|
+
return prefix & items & ")";
|
|
745
|
+
end;
|
|
746
|
+
|
|
747
|
+
-- The group holding the given positional and keyword arguments
|
|
748
|
+
function p_group(positional_items, keyword_items : string) return arg_t is
|
|
749
|
+
constant positional : string := p_group_text(p_positional_group, positional_items);
|
|
750
|
+
constant keywords : string := p_group_text(p_keyword_group, keyword_items);
|
|
751
|
+
begin
|
|
752
|
+
if positional = "" then
|
|
753
|
+
return (p_group_arg & integer'image(0), keywords);
|
|
754
|
+
elsif keywords = "" then
|
|
755
|
+
return (p_group_arg & integer'image(positional'length), positional);
|
|
756
|
+
end if;
|
|
757
|
+
return (p_group_arg & integer'image(positional'length), positional & ", " & keywords);
|
|
758
|
+
end;
|
|
759
|
+
|
|
760
|
+
impure function "&"(l, r : arg_t) return arg_t is
|
|
761
|
+
constant l_positional : string := p_positional_items(l);
|
|
762
|
+
constant l_keywords : string := p_keyword_items(l);
|
|
763
|
+
constant r_positional : string := p_positional_items(r);
|
|
764
|
+
constant r_keywords : string := p_keyword_items(r);
|
|
765
|
+
begin
|
|
766
|
+
if l.name = p_ignore_arg then
|
|
767
|
+
return r;
|
|
768
|
+
elsif r.name = p_ignore_arg then
|
|
769
|
+
return l;
|
|
770
|
+
elsif l_keywords /= "" and r_positional /= "" then
|
|
771
|
+
-- Python's own rule
|
|
772
|
+
failure(python_logger, "positional argument after keyword arguments");
|
|
773
|
+
return null_arg;
|
|
774
|
+
end if;
|
|
775
|
+
|
|
776
|
+
return p_group(p_join(l_positional, r_positional, " "), p_join(l_keywords, r_keywords, ", "));
|
|
777
|
+
end;
|
|
778
|
+
|
|
779
|
+
impure function to_call_str(
|
|
780
|
+
identifier : string; arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10 : arg_t := null_arg
|
|
781
|
+
) return string is
|
|
782
|
+
variable result : line;
|
|
783
|
+
variable first : boolean := true;
|
|
784
|
+
|
|
785
|
+
procedure append(value : arg_t) is
|
|
786
|
+
begin
|
|
787
|
+
if value.name = p_ignore_arg then
|
|
788
|
+
return;
|
|
789
|
+
end if;
|
|
790
|
+
if not first then
|
|
791
|
+
swrite(result, ", ");
|
|
792
|
+
end if;
|
|
793
|
+
first := false;
|
|
794
|
+
if value.name = p_positional_arg or p_is_group(value) then
|
|
795
|
+
-- A group is spliced into the call like a positional argument
|
|
796
|
+
swrite(result, value.value);
|
|
797
|
+
else
|
|
798
|
+
swrite(result, value.name & "=" & value.value);
|
|
799
|
+
end if;
|
|
800
|
+
end;
|
|
801
|
+
begin
|
|
802
|
+
swrite(result, identifier & "(");
|
|
803
|
+
append(arg1);
|
|
804
|
+
append(arg2);
|
|
805
|
+
append(arg3);
|
|
806
|
+
append(arg4);
|
|
807
|
+
append(arg5);
|
|
808
|
+
append(arg6);
|
|
809
|
+
append(arg7);
|
|
810
|
+
append(arg8);
|
|
811
|
+
append(arg9);
|
|
812
|
+
append(arg10);
|
|
813
|
+
swrite(result, ")");
|
|
814
|
+
|
|
815
|
+
return result.all;
|
|
816
|
+
end;
|
|
817
|
+
|
|
818
|
+
impure function call_integer_w_arg(
|
|
819
|
+
identifier : string; arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10 : arg_t := null_arg;
|
|
820
|
+
session : python_session_t := default_session
|
|
821
|
+
) return integer is
|
|
822
|
+
begin
|
|
823
|
+
return eval(to_call_str(identifier, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10), session);
|
|
824
|
+
end;
|
|
825
|
+
|
|
826
|
+
procedure call(
|
|
827
|
+
identifier : string; arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10 : arg_t := null_arg;
|
|
828
|
+
session : python_session_t := default_session
|
|
829
|
+
) is
|
|
830
|
+
begin
|
|
831
|
+
exec(to_call_str(identifier, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10), session);
|
|
832
|
+
end;
|
|
833
|
+
|
|
834
|
+
impure function call_integer_vector(
|
|
835
|
+
identifier : string; arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10 : arg_t := null_arg;
|
|
836
|
+
session : python_session_t := default_session
|
|
837
|
+
) return integer_vector is
|
|
838
|
+
begin
|
|
839
|
+
return eval(to_call_str(identifier, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10), session);
|
|
840
|
+
end;
|
|
841
|
+
|
|
842
|
+
impure function call_real(
|
|
843
|
+
identifier : string; arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10 : arg_t := null_arg;
|
|
844
|
+
session : python_session_t := default_session
|
|
845
|
+
) return real is
|
|
846
|
+
begin
|
|
847
|
+
return eval(to_call_str(identifier, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10), session);
|
|
848
|
+
end;
|
|
849
|
+
|
|
850
|
+
-----------------------------------------------------------------------------
|
|
851
|
+
-- Operations implemented by the Python bridge (NVC, GHDL and Questa)
|
|
852
|
+
-----------------------------------------------------------------------------
|
|
853
|
+
-- Python represents std_ulogic values by these characters
|
|
854
|
+
constant p_std_ulogic_characters : string(1 to 9) := "UX01ZWLH-";
|
|
855
|
+
|
|
856
|
+
function p_to_std_ulogic(value : character) return std_ulogic is
|
|
857
|
+
begin
|
|
858
|
+
for idx in p_std_ulogic_characters'range loop
|
|
859
|
+
if p_std_ulogic_characters(idx) = value then
|
|
860
|
+
return std_ulogic'val(idx - 1);
|
|
861
|
+
end if;
|
|
862
|
+
end loop;
|
|
863
|
+
-- The bridge only returns the characters above
|
|
864
|
+
return 'X';
|
|
865
|
+
end;
|
|
866
|
+
|
|
867
|
+
-- The elements of the characters, the first character becoming the leftmost element
|
|
868
|
+
function p_to_std_ulogic_vector(value : string) return std_ulogic_vector is
|
|
869
|
+
alias normalized : string(1 to value'length) is value;
|
|
870
|
+
variable result : std_ulogic_vector(value'length - 1 downto 0);
|
|
871
|
+
begin
|
|
872
|
+
for idx in normalized'range loop
|
|
873
|
+
result(value'length - idx) := p_to_std_ulogic(normalized(idx));
|
|
874
|
+
end loop;
|
|
875
|
+
return result;
|
|
876
|
+
end;
|
|
877
|
+
|
|
878
|
+
-----------------------------------------------------------------------------
|
|
879
|
+
-- exec
|
|
880
|
+
-----------------------------------------------------------------------------
|
|
881
|
+
-- True when the file name is absolute: /a/b, \\server\share\a, C:\a or C:/a
|
|
882
|
+
function p_is_absolute(file_name : string) return boolean is
|
|
883
|
+
alias name : string(1 to file_name'length) is file_name;
|
|
884
|
+
begin
|
|
885
|
+
if name'length = 0 then
|
|
886
|
+
return false;
|
|
887
|
+
elsif name(1) = '/' or name(1) = '\' then
|
|
888
|
+
return true;
|
|
889
|
+
elsif name'length >= 2 then
|
|
890
|
+
-- A Windows drive
|
|
891
|
+
return name(2) = ':';
|
|
892
|
+
end if;
|
|
893
|
+
return false;
|
|
894
|
+
end;
|
|
895
|
+
|
|
896
|
+
-- The file name of exec_file, a relative one taken from the directory of the
|
|
897
|
+
-- testbench file like the file names of the other VUnit subprograms
|
|
898
|
+
impure function p_file_path(file_name : string) return string is
|
|
899
|
+
begin
|
|
900
|
+
if p_is_absolute(file_name) then
|
|
901
|
+
return file_name;
|
|
902
|
+
end if;
|
|
903
|
+
return join(tb_path(get_cfg(runner_state)), file_name);
|
|
904
|
+
end;
|
|
905
|
+
|
|
906
|
+
procedure exec_file(file_name : string; session : python_session_t := default_session) is
|
|
907
|
+
variable ok : boolean;
|
|
908
|
+
begin
|
|
909
|
+
ok := p_exec_file(p_file_path(file_name), session);
|
|
910
|
+
end;
|
|
911
|
+
|
|
912
|
+
-----------------------------------------------------------------------------
|
|
913
|
+
-- eval
|
|
914
|
+
-----------------------------------------------------------------------------
|
|
915
|
+
impure function eval_boolean(
|
|
916
|
+
expr : string; session : python_session_t := default_session
|
|
917
|
+
) return boolean is
|
|
918
|
+
begin
|
|
919
|
+
if p_eval(expr, p_kind_boolean, -1, p_eval_operation(expr, session), session) then
|
|
920
|
+
return p_result_integer /= 0;
|
|
921
|
+
end if;
|
|
922
|
+
return false;
|
|
923
|
+
end;
|
|
924
|
+
|
|
925
|
+
impure function eval_std_ulogic(
|
|
926
|
+
expr : string; session : python_session_t := default_session
|
|
927
|
+
) return std_ulogic is
|
|
928
|
+
begin
|
|
929
|
+
if p_eval(expr, p_kind_std_ulogic, -1, p_eval_operation(expr, session), session) then
|
|
930
|
+
return p_to_std_ulogic(p_result_string(1));
|
|
931
|
+
end if;
|
|
932
|
+
return 'U';
|
|
933
|
+
end;
|
|
934
|
+
|
|
935
|
+
impure function eval_std_ulogic_vector(
|
|
936
|
+
expr : string; session : python_session_t := default_session
|
|
937
|
+
) return std_ulogic_vector is
|
|
938
|
+
begin
|
|
939
|
+
if p_eval(expr, p_kind_std_ulogic_vector, -1, p_eval_operation(expr, session), session) then
|
|
940
|
+
return p_to_std_ulogic_vector(p_result_string);
|
|
941
|
+
end if;
|
|
942
|
+
return "";
|
|
943
|
+
end;
|
|
944
|
+
|
|
945
|
+
impure function eval_integer_array(
|
|
946
|
+
expr : string; session : python_session_t := default_session
|
|
947
|
+
) return integer_array_t is
|
|
948
|
+
begin
|
|
949
|
+
if p_eval(expr, p_kind_integer_array, -1, p_eval_operation(expr, session), session) then
|
|
950
|
+
return p_result_integer_array;
|
|
951
|
+
end if;
|
|
952
|
+
return null_integer_array;
|
|
953
|
+
end;
|
|
954
|
+
|
|
955
|
+
procedure eval_std_ulogic_vector(
|
|
956
|
+
expr : string; result : out std_ulogic_vector; session : python_session_t := default_session
|
|
957
|
+
) is
|
|
958
|
+
begin
|
|
959
|
+
if p_eval(expr, p_kind_std_ulogic_vector, result'length, p_eval_operation(expr, session), session) then
|
|
960
|
+
result := p_to_std_ulogic_vector(p_result_string);
|
|
961
|
+
end if;
|
|
962
|
+
end;
|
|
963
|
+
|
|
964
|
+
procedure eval_signed(
|
|
965
|
+
expr : string; result : out signed; session : python_session_t := default_session
|
|
966
|
+
) is
|
|
967
|
+
begin
|
|
968
|
+
if p_eval(expr, p_kind_signed, result'length, p_eval_operation(expr, session), session) then
|
|
969
|
+
result := signed(p_to_std_ulogic_vector(p_result_string));
|
|
970
|
+
end if;
|
|
971
|
+
end;
|
|
972
|
+
|
|
973
|
+
procedure eval_unsigned(
|
|
974
|
+
expr : string; result : out unsigned; session : python_session_t := default_session
|
|
975
|
+
) is
|
|
976
|
+
begin
|
|
977
|
+
if p_eval(expr, p_kind_unsigned, result'length, p_eval_operation(expr, session), session) then
|
|
978
|
+
result := unsigned(p_to_std_ulogic_vector(p_result_string));
|
|
979
|
+
end if;
|
|
980
|
+
end;
|
|
981
|
+
|
|
982
|
+
-----------------------------------------------------------------------------
|
|
983
|
+
-- call
|
|
984
|
+
-----------------------------------------------------------------------------
|
|
985
|
+
impure function call_real_vector(
|
|
986
|
+
identifier : string; arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10 : arg_t := null_arg;
|
|
987
|
+
session : python_session_t := default_session
|
|
988
|
+
) return real_vector is
|
|
989
|
+
begin
|
|
990
|
+
return eval_real_vector(
|
|
991
|
+
to_call_str(identifier, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10), session
|
|
992
|
+
);
|
|
993
|
+
end;
|
|
994
|
+
|
|
995
|
+
impure function call_string(
|
|
996
|
+
identifier : string; arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10 : arg_t := null_arg;
|
|
997
|
+
session : python_session_t := default_session
|
|
998
|
+
) return string is
|
|
999
|
+
begin
|
|
1000
|
+
return eval_string(
|
|
1001
|
+
to_call_str(identifier, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10), session
|
|
1002
|
+
);
|
|
1003
|
+
end;
|
|
1004
|
+
|
|
1005
|
+
impure function call_integer_vector_ptr(
|
|
1006
|
+
identifier : string; arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10 : arg_t := null_arg;
|
|
1007
|
+
session : python_session_t := default_session
|
|
1008
|
+
) return integer_vector_ptr_t is
|
|
1009
|
+
begin
|
|
1010
|
+
return eval_integer_vector_ptr(
|
|
1011
|
+
to_call_str(identifier, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10), session
|
|
1012
|
+
);
|
|
1013
|
+
end;
|
|
1014
|
+
|
|
1015
|
+
impure function call_boolean(
|
|
1016
|
+
identifier : string; arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10 : arg_t := null_arg;
|
|
1017
|
+
session : python_session_t := default_session
|
|
1018
|
+
) return boolean is
|
|
1019
|
+
begin
|
|
1020
|
+
return eval_boolean(
|
|
1021
|
+
to_call_str(identifier, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10), session
|
|
1022
|
+
);
|
|
1023
|
+
end;
|
|
1024
|
+
|
|
1025
|
+
impure function call_std_ulogic(
|
|
1026
|
+
identifier : string; arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10 : arg_t := null_arg;
|
|
1027
|
+
session : python_session_t := default_session
|
|
1028
|
+
) return std_ulogic is
|
|
1029
|
+
begin
|
|
1030
|
+
return eval_std_ulogic(
|
|
1031
|
+
to_call_str(identifier, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10), session
|
|
1032
|
+
);
|
|
1033
|
+
end;
|
|
1034
|
+
|
|
1035
|
+
impure function call_std_ulogic_vector(
|
|
1036
|
+
identifier : string; arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10 : arg_t := null_arg;
|
|
1037
|
+
session : python_session_t := default_session
|
|
1038
|
+
) return std_ulogic_vector is
|
|
1039
|
+
begin
|
|
1040
|
+
return eval_std_ulogic_vector(
|
|
1041
|
+
to_call_str(identifier, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10), session
|
|
1042
|
+
);
|
|
1043
|
+
end;
|
|
1044
|
+
|
|
1045
|
+
impure function call_integer_array(
|
|
1046
|
+
identifier : string; arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10 : arg_t := null_arg;
|
|
1047
|
+
session : python_session_t := default_session
|
|
1048
|
+
) return integer_array_t is
|
|
1049
|
+
begin
|
|
1050
|
+
return eval_integer_array(
|
|
1051
|
+
to_call_str(identifier, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10), session
|
|
1052
|
+
);
|
|
1053
|
+
end;
|
|
1054
|
+
|
|
1055
|
+
procedure call_std_ulogic_vector(
|
|
1056
|
+
identifier : string; result : out std_ulogic_vector;
|
|
1057
|
+
arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10 : arg_t := null_arg;
|
|
1058
|
+
session : python_session_t := default_session
|
|
1059
|
+
) is
|
|
1060
|
+
begin
|
|
1061
|
+
eval_std_ulogic_vector(
|
|
1062
|
+
to_call_str(identifier, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10), result, session
|
|
1063
|
+
);
|
|
1064
|
+
end;
|
|
1065
|
+
|
|
1066
|
+
procedure call_signed(
|
|
1067
|
+
identifier : string; result : out signed;
|
|
1068
|
+
arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10 : arg_t := null_arg;
|
|
1069
|
+
session : python_session_t := default_session
|
|
1070
|
+
) is
|
|
1071
|
+
begin
|
|
1072
|
+
eval_signed(
|
|
1073
|
+
to_call_str(identifier, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10), result, session
|
|
1074
|
+
);
|
|
1075
|
+
end;
|
|
1076
|
+
|
|
1077
|
+
procedure call_unsigned(
|
|
1078
|
+
identifier : string; result : out unsigned;
|
|
1079
|
+
arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10 : arg_t := null_arg;
|
|
1080
|
+
session : python_session_t := default_session
|
|
1081
|
+
) is
|
|
1082
|
+
begin
|
|
1083
|
+
eval_unsigned(
|
|
1084
|
+
to_call_str(identifier, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10), result, session
|
|
1085
|
+
);
|
|
1086
|
+
end;
|
|
1087
|
+
end package body;
|