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.
Files changed (34) hide show
  1. vunit_python_bridge/__init__.py +92 -0
  2. vunit_python_bridge/bin/vunit_python_bridge-cp310-win_amd64.dll +0 -0
  3. vunit_python_bridge/bin/vunit_python_bridge-cp311-win_amd64.dll +0 -0
  4. vunit_python_bridge/bin/vunit_python_bridge-cp312-win_amd64.dll +0 -0
  5. vunit_python_bridge/bin/vunit_python_bridge-cp313-win_amd64.dll +0 -0
  6. vunit_python_bridge/bin/vunit_python_bridge-cp314-win_amd64.dll +0 -0
  7. vunit_python_bridge/bridge.py +171 -0
  8. vunit_python_bridge/foreign_application.py +90 -0
  9. vunit_python_bridge/hdl/src/python_bridge_pkg.vhd.in +91 -0
  10. vunit_python_bridge/hdl/src/python_context.vhd +13 -0
  11. vunit_python_bridge/hdl/src/python_ffi_pkg_bridge.vhd +507 -0
  12. vunit_python_bridge/hdl/src/python_pkg.vhd +1087 -0
  13. vunit_python_bridge/hdl/src/python_pkg_vhpi.vhd +270 -0
  14. vunit_python_bridge/hdl/tools/generate_python_pkg.py +386 -0
  15. vunit_python_bridge/hdl/tools/python_pkg.vhd.in +765 -0
  16. vunit_python_bridge/native/arguments.c +191 -0
  17. vunit_python_bridge/native/bridge.h +117 -0
  18. vunit_python_bridge/native/config.c +201 -0
  19. vunit_python_bridge/native/error.c +120 -0
  20. vunit_python_bridge/native/fli.c +98 -0
  21. vunit_python_bridge/native/interpreter.c +271 -0
  22. vunit_python_bridge/native/operations.c +239 -0
  23. vunit_python_bridge/native/vhpi/python_pkg.c +125 -0
  24. vunit_python_bridge/native/vhpi/python_pkg.h +31 -0
  25. vunit_python_bridge/native/vhpi/python_pkg_vhpi.c +366 -0
  26. vunit_python_bridge/native_library.py +455 -0
  27. vunit_python_bridge/runtime.py +645 -0
  28. vunit_python_bridge/simulator_hooks.py +141 -0
  29. vunit_python_bridge/vunit_pkg.toml +17 -0
  30. vunit_python_bridge-0.1.0.dist-info/METADATA +116 -0
  31. vunit_python_bridge-0.1.0.dist-info/RECORD +34 -0
  32. vunit_python_bridge-0.1.0.dist-info/WHEEL +5 -0
  33. vunit_python_bridge-0.1.0.dist-info/licenses/LICENSE +373 -0
  34. 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;