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,507 @@
|
|
|
1
|
+
-- This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
-- License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
|
3
|
+
-- You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
4
|
+
--
|
|
5
|
+
-- Copyright (c) 2014-2026, Lars Asplund lars.anders.asplund@gmail.com
|
|
6
|
+
--
|
|
7
|
+
-- The foreign language interface of the Python package for NVC and GHDL,
|
|
8
|
+
-- implemented with the VUnit Python bridge (src/vunit_python_bridge). It provides
|
|
9
|
+
-- the same subprograms as the FLI and VHPI variants but over the private
|
|
10
|
+
-- python_bridge_pkg, which the setup function of the package generates.
|
|
11
|
+
--
|
|
12
|
+
-- Deviations from the other variants:
|
|
13
|
+
-- * The subprograms are impure since they call impure foreign subprograms.
|
|
14
|
+
-- * Errors are reported as failures on the logger of the session they were
|
|
15
|
+
-- performed in rather than aborting the simulation directly, which makes
|
|
16
|
+
-- them observable from VHDL.
|
|
17
|
+
-- * Sessions other than the default one are supported.
|
|
18
|
+
--
|
|
19
|
+
-- The p_ prefixed declarations are the private primitives the bridge
|
|
20
|
+
-- operations of python_pkg are built on. They are not part of the API. The FLI and VHPI
|
|
21
|
+
-- variants of this package declare the same primitives and implement them by
|
|
22
|
+
-- reporting a failure.
|
|
23
|
+
|
|
24
|
+
library vunit_lib;
|
|
25
|
+
use vunit_lib.id_pkg.all;
|
|
26
|
+
use vunit_lib.integer_array_pkg.all;
|
|
27
|
+
use vunit_lib.integer_vector_ptr_pkg.all;
|
|
28
|
+
use vunit_lib.logger_pkg.all;
|
|
29
|
+
use work.python_bridge_pkg.all;
|
|
30
|
+
|
|
31
|
+
package python_ffi_pkg is
|
|
32
|
+
-- The identity of the Python interface. It is the identity of
|
|
33
|
+
-- python_logger and the parent of the identities of the sessions created
|
|
34
|
+
-- from a name.
|
|
35
|
+
constant p_python_id : id_t := get_id("python_bridge:python");
|
|
36
|
+
|
|
37
|
+
-- Logger of the Python interface. It is the parent of the session loggers
|
|
38
|
+
-- an operation reports its errors on, so log levels and log handler
|
|
39
|
+
-- settings made on python_logger apply to all sessions. It is also the
|
|
40
|
+
-- logger used to report what has no session of its own: an argument value
|
|
41
|
+
-- that cannot be converted to Python and the transfer of an integer_array_t.
|
|
42
|
+
constant python_logger : logger_t := get_logger(p_python_id);
|
|
43
|
+
|
|
44
|
+
-- A session is a Python namespace. Sessions are isolated from each other
|
|
45
|
+
-- and have an identity, which is what they are created from:
|
|
46
|
+
--
|
|
47
|
+
-- constant golden_model : python_session_t := new_session("golden_model");
|
|
48
|
+
--
|
|
49
|
+
-- new_session(name) creates the identity name under the identity of the
|
|
50
|
+
-- Python interface, while new_session(id) takes an existing identity, which
|
|
51
|
+
-- puts the session anywhere in the identity tree, for example under the
|
|
52
|
+
-- identity of what it serves. Two sessions with the same identity are the
|
|
53
|
+
-- same session.
|
|
54
|
+
--
|
|
55
|
+
-- The Python namespace is created on first use and the operations of a
|
|
56
|
+
-- session report their errors on get_logger(get_id(session)). The default
|
|
57
|
+
-- session is the __main__ namespace.
|
|
58
|
+
type python_session_t is record
|
|
59
|
+
p_data : integer_vector_ptr_t;
|
|
60
|
+
end record;
|
|
61
|
+
|
|
62
|
+
impure function new_session(name : string) return python_session_t;
|
|
63
|
+
impure function new_session(id : id_t) return python_session_t;
|
|
64
|
+
|
|
65
|
+
-- The identity of a session, which is what two sessions are compared by
|
|
66
|
+
impure function get_id(session : python_session_t) return id_t;
|
|
67
|
+
|
|
68
|
+
-- The name of the identity of a session, without hierarchy
|
|
69
|
+
impure function name(session : python_session_t) return string;
|
|
70
|
+
|
|
71
|
+
-- The session the operations are performed in when no other one is given.
|
|
72
|
+
-- It is created the way new_session does, which cannot be called here since
|
|
73
|
+
-- its body is not elaborated until the package body is.
|
|
74
|
+
constant default_session : python_session_t :=
|
|
75
|
+
(p_data => new_integer_vector_ptr(1, value => to_integer(get_id("default", parent => p_python_id))));
|
|
76
|
+
|
|
77
|
+
-- Start the embedded Python interpreter eagerly. Optional and idempotent:
|
|
78
|
+
-- without it the interpreter starts on first use.
|
|
79
|
+
procedure python_setup;
|
|
80
|
+
|
|
81
|
+
-- Release the values staged for integer_array_t arguments. Optional: they
|
|
82
|
+
-- are released when the simulator process ends. The interpreter is not
|
|
83
|
+
-- finalized, so later operations keep working.
|
|
84
|
+
procedure python_cleanup;
|
|
85
|
+
|
|
86
|
+
-- Execute Python source code in the namespace of a session
|
|
87
|
+
procedure exec(code : string; session : python_session_t := default_session);
|
|
88
|
+
|
|
89
|
+
-- Evaluate a Python expression and convert its value to a VHDL type
|
|
90
|
+
impure function eval_integer(expr : string; session : python_session_t := default_session) return integer;
|
|
91
|
+
alias eval is eval_integer[string, python_session_t return integer];
|
|
92
|
+
|
|
93
|
+
impure function eval_real(expr : string; session : python_session_t := default_session) return real;
|
|
94
|
+
alias eval is eval_real[string, python_session_t return real];
|
|
95
|
+
|
|
96
|
+
impure function eval_integer_vector(
|
|
97
|
+
expr : string; session : python_session_t := default_session
|
|
98
|
+
) return integer_vector;
|
|
99
|
+
alias eval is eval_integer_vector[string, python_session_t return integer_vector];
|
|
100
|
+
|
|
101
|
+
impure function eval_real_vector(
|
|
102
|
+
expr : string; session : python_session_t := default_session
|
|
103
|
+
) return real_vector;
|
|
104
|
+
alias eval is eval_real_vector[string, python_session_t return real_vector];
|
|
105
|
+
|
|
106
|
+
impure function eval_string(expr : string; session : python_session_t := default_session) return string;
|
|
107
|
+
alias eval is eval_string[string, python_session_t return string];
|
|
108
|
+
|
|
109
|
+
-----------------------------------------------------------------------------
|
|
110
|
+
-- Private, the primitives the bridge operations of python_pkg are built on
|
|
111
|
+
-----------------------------------------------------------------------------
|
|
112
|
+
-- Result kinds, must match src/vunit_python_bridge/runtime.py
|
|
113
|
+
constant p_kind_integer : integer := 0;
|
|
114
|
+
constant p_kind_real : integer := 1;
|
|
115
|
+
constant p_kind_boolean : integer := 2;
|
|
116
|
+
constant p_kind_string : integer := 3;
|
|
117
|
+
constant p_kind_std_ulogic : integer := 4;
|
|
118
|
+
constant p_kind_std_ulogic_vector : integer := 5;
|
|
119
|
+
constant p_kind_signed : integer := 6;
|
|
120
|
+
constant p_kind_unsigned : integer := 7;
|
|
121
|
+
constant p_kind_integer_array : integer := 8;
|
|
122
|
+
constant p_kind_integer_vector : integer := 9;
|
|
123
|
+
constant p_kind_real_vector : integer := 10;
|
|
124
|
+
|
|
125
|
+
-- Names of the operations, used in the error messages
|
|
126
|
+
impure function p_exec_operation(session : python_session_t := default_session) return string;
|
|
127
|
+
impure function p_exec_file_operation(
|
|
128
|
+
file_name : string; session : python_session_t := default_session
|
|
129
|
+
) return string;
|
|
130
|
+
impure function p_eval_operation(expr : string; session : python_session_t := default_session) return string;
|
|
131
|
+
|
|
132
|
+
-- The error of the last failed bridge operation, typically a Python traceback
|
|
133
|
+
impure function p_error_text return string;
|
|
134
|
+
|
|
135
|
+
-- Report a failed operation (status /= 0) with its error. True if it succeeded.
|
|
136
|
+
impure function p_succeeded(
|
|
137
|
+
status : integer; operation : string; logger : logger_t := python_logger
|
|
138
|
+
) return boolean;
|
|
139
|
+
|
|
140
|
+
-- Transfer a string to the bridge buffer. Returns the bridge status.
|
|
141
|
+
impure function p_send(text : string) return integer;
|
|
142
|
+
|
|
143
|
+
-- Start an operation in a session
|
|
144
|
+
impure function p_begin(session : python_session_t; operation : string) return boolean;
|
|
145
|
+
|
|
146
|
+
-- Execute text as Python source code (is_file = 0) or as a Python file name (is_file = 1)
|
|
147
|
+
impure function p_exec(
|
|
148
|
+
text : string;
|
|
149
|
+
is_file : integer;
|
|
150
|
+
operation : string;
|
|
151
|
+
session : python_session_t := default_session
|
|
152
|
+
) return boolean;
|
|
153
|
+
|
|
154
|
+
-- Execute the Python file with the given name
|
|
155
|
+
impure function p_exec_file(
|
|
156
|
+
file_name : string; session : python_session_t := default_session
|
|
157
|
+
) return boolean;
|
|
158
|
+
|
|
159
|
+
-- Evaluate expr and convert the value to the VHDL type given by kind. width
|
|
160
|
+
-- is the length of a std_ulogic_vector, signed or unsigned result, -1 when
|
|
161
|
+
-- it is not known.
|
|
162
|
+
impure function p_eval(
|
|
163
|
+
expr : string;
|
|
164
|
+
kind : integer;
|
|
165
|
+
width : integer;
|
|
166
|
+
operation : string;
|
|
167
|
+
session : python_session_t := default_session
|
|
168
|
+
) return boolean;
|
|
169
|
+
|
|
170
|
+
-- The result of the last evaluation
|
|
171
|
+
impure function p_result_integer return integer;
|
|
172
|
+
impure function p_result_string return string;
|
|
173
|
+
impure function p_result_integer_vector return integer_vector;
|
|
174
|
+
impure function p_result_real_vector return real_vector;
|
|
175
|
+
impure function p_result_integer_array return integer_array_t;
|
|
176
|
+
|
|
177
|
+
-- Transfer an integer_array_t to Python and return the id it is staged
|
|
178
|
+
-- under, -1 on failure. Python source code refers to the value as
|
|
179
|
+
-- __vunit__.staged(<id>).
|
|
180
|
+
impure function p_stage_array(arr : integer_array_t; operation : string) return integer;
|
|
181
|
+
end package;
|
|
182
|
+
|
|
183
|
+
package body python_ffi_pkg is
|
|
184
|
+
-----------------------------------------------------------------------------
|
|
185
|
+
-- Sessions
|
|
186
|
+
-----------------------------------------------------------------------------
|
|
187
|
+
impure function new_session(name : string) return python_session_t is
|
|
188
|
+
begin
|
|
189
|
+
return new_session(get_id(name, parent => p_python_id));
|
|
190
|
+
end;
|
|
191
|
+
|
|
192
|
+
impure function new_session(id : id_t) return python_session_t is
|
|
193
|
+
begin
|
|
194
|
+
return (p_data => new_integer_vector_ptr(1, value => to_integer(id)));
|
|
195
|
+
end;
|
|
196
|
+
|
|
197
|
+
impure function get_id(session : python_session_t) return id_t is
|
|
198
|
+
begin
|
|
199
|
+
return to_id(get(session.p_data, 0));
|
|
200
|
+
end;
|
|
201
|
+
|
|
202
|
+
impure function name(session : python_session_t) return string is
|
|
203
|
+
begin
|
|
204
|
+
return name(get_id(session));
|
|
205
|
+
end;
|
|
206
|
+
|
|
207
|
+
impure function p_is_default(session : python_session_t) return boolean is
|
|
208
|
+
begin
|
|
209
|
+
return get_id(session) = get_id(default_session);
|
|
210
|
+
end;
|
|
211
|
+
|
|
212
|
+
-----------------------------------------------------------------------------
|
|
213
|
+
-- Operation names
|
|
214
|
+
-----------------------------------------------------------------------------
|
|
215
|
+
impure function p_exec_operation(session : python_session_t := default_session) return string is
|
|
216
|
+
begin
|
|
217
|
+
if p_is_default(session) then
|
|
218
|
+
return "exec";
|
|
219
|
+
end if;
|
|
220
|
+
return "exec(session => """ & name(session) & """)";
|
|
221
|
+
end;
|
|
222
|
+
|
|
223
|
+
impure function p_exec_file_operation(
|
|
224
|
+
file_name : string; session : python_session_t := default_session
|
|
225
|
+
) return string is
|
|
226
|
+
begin
|
|
227
|
+
if p_is_default(session) then
|
|
228
|
+
return "exec_file(""" & file_name & """)";
|
|
229
|
+
end if;
|
|
230
|
+
return "exec_file(""" & file_name & """, session => """ & name(session) & """)";
|
|
231
|
+
end;
|
|
232
|
+
|
|
233
|
+
impure function p_eval_operation(expr : string; session : python_session_t := default_session) return string is
|
|
234
|
+
begin
|
|
235
|
+
if p_is_default(session) then
|
|
236
|
+
return "eval(""" & expr & """)";
|
|
237
|
+
end if;
|
|
238
|
+
return "eval(""" & expr & """, session => """ & name(session) & """)";
|
|
239
|
+
end;
|
|
240
|
+
|
|
241
|
+
-----------------------------------------------------------------------------
|
|
242
|
+
-- Transfers through the bridge
|
|
243
|
+
-----------------------------------------------------------------------------
|
|
244
|
+
impure function p_error_text return string is
|
|
245
|
+
constant len : natural := vpy_error_length;
|
|
246
|
+
variable result : string(1 to len);
|
|
247
|
+
variable chunk : string_chunk_t;
|
|
248
|
+
variable offset, n : natural := 0;
|
|
249
|
+
begin
|
|
250
|
+
while offset < len loop
|
|
251
|
+
n := minimum(chunk_length, len - offset);
|
|
252
|
+
vpy_error_read(chunk, offset, n);
|
|
253
|
+
result(offset + 1 to offset + n) := chunk(1 to n);
|
|
254
|
+
offset := offset + n;
|
|
255
|
+
end loop;
|
|
256
|
+
return result;
|
|
257
|
+
end;
|
|
258
|
+
|
|
259
|
+
impure function p_succeeded(
|
|
260
|
+
status : integer; operation : string; logger : logger_t := python_logger
|
|
261
|
+
) return boolean is
|
|
262
|
+
begin
|
|
263
|
+
if status = 0 then
|
|
264
|
+
return true;
|
|
265
|
+
end if;
|
|
266
|
+
failure(logger, operation & " failed:" & LF & p_error_text);
|
|
267
|
+
return false;
|
|
268
|
+
end;
|
|
269
|
+
|
|
270
|
+
impure function p_send(text : string) return integer is
|
|
271
|
+
alias normalized : string(1 to text'length) is text;
|
|
272
|
+
variable chunk : string_chunk_t;
|
|
273
|
+
variable offset, n : natural := 0;
|
|
274
|
+
variable status : integer;
|
|
275
|
+
begin
|
|
276
|
+
status := vpy_buffer_clear;
|
|
277
|
+
while offset < text'length and status = 0 loop
|
|
278
|
+
n := minimum(chunk_length, text'length - offset);
|
|
279
|
+
chunk(1 to n) := normalized(offset + 1 to offset + n);
|
|
280
|
+
status := vpy_buffer_append(chunk, n);
|
|
281
|
+
offset := offset + n;
|
|
282
|
+
end loop;
|
|
283
|
+
return status;
|
|
284
|
+
end;
|
|
285
|
+
|
|
286
|
+
-- The full name of the identity of the session is the key of its Python
|
|
287
|
+
-- namespace, so that two sessions with the same name but different
|
|
288
|
+
-- identities are namespaces of their own.
|
|
289
|
+
impure function p_begin(session : python_session_t; operation : string) return boolean is
|
|
290
|
+
constant logger : logger_t := get_logger(get_id(session));
|
|
291
|
+
begin
|
|
292
|
+
return p_succeeded(p_send(full_name(get_id(session))), operation, logger)
|
|
293
|
+
and p_succeeded(vpy_begin, operation, logger);
|
|
294
|
+
end;
|
|
295
|
+
|
|
296
|
+
impure function p_exec(
|
|
297
|
+
text : string;
|
|
298
|
+
is_file : integer;
|
|
299
|
+
operation : string;
|
|
300
|
+
session : python_session_t := default_session
|
|
301
|
+
) return boolean is
|
|
302
|
+
constant logger : logger_t := get_logger(get_id(session));
|
|
303
|
+
begin
|
|
304
|
+
return p_begin(session, operation)
|
|
305
|
+
and p_succeeded(p_send(text), operation, logger)
|
|
306
|
+
and p_succeeded(vpy_execute(is_file), operation, logger);
|
|
307
|
+
end;
|
|
308
|
+
|
|
309
|
+
impure function p_exec_file(
|
|
310
|
+
file_name : string; session : python_session_t := default_session
|
|
311
|
+
) return boolean is
|
|
312
|
+
begin
|
|
313
|
+
return p_exec(file_name, 1, p_exec_file_operation(file_name, session), session);
|
|
314
|
+
end;
|
|
315
|
+
|
|
316
|
+
impure function p_eval(
|
|
317
|
+
expr : string;
|
|
318
|
+
kind : integer;
|
|
319
|
+
width : integer;
|
|
320
|
+
operation : string;
|
|
321
|
+
session : python_session_t := default_session
|
|
322
|
+
) return boolean is
|
|
323
|
+
constant logger : logger_t := get_logger(get_id(session));
|
|
324
|
+
begin
|
|
325
|
+
return p_begin(session, operation)
|
|
326
|
+
and p_succeeded(p_send(expr), operation, logger)
|
|
327
|
+
and p_succeeded(vpy_eval(kind, width), operation, logger);
|
|
328
|
+
end;
|
|
329
|
+
|
|
330
|
+
-----------------------------------------------------------------------------
|
|
331
|
+
-- Results
|
|
332
|
+
-----------------------------------------------------------------------------
|
|
333
|
+
impure function p_result_integer return integer is
|
|
334
|
+
begin
|
|
335
|
+
return vpy_result_integer;
|
|
336
|
+
end;
|
|
337
|
+
|
|
338
|
+
impure function p_result_string return string is
|
|
339
|
+
constant len : natural := vpy_result_meta(0);
|
|
340
|
+
variable result : string(1 to len);
|
|
341
|
+
variable chunk : string_chunk_t;
|
|
342
|
+
variable offset, n : natural := 0;
|
|
343
|
+
begin
|
|
344
|
+
while offset < len loop
|
|
345
|
+
n := minimum(chunk_length, len - offset);
|
|
346
|
+
vpy_result_read_string(chunk, offset, n);
|
|
347
|
+
result(offset + 1 to offset + n) := chunk(1 to n);
|
|
348
|
+
offset := offset + n;
|
|
349
|
+
end loop;
|
|
350
|
+
return result;
|
|
351
|
+
end;
|
|
352
|
+
|
|
353
|
+
impure function p_result_integer_vector return integer_vector is
|
|
354
|
+
constant len : natural := vpy_result_meta(0);
|
|
355
|
+
variable result : integer_vector(0 to len - 1);
|
|
356
|
+
variable chunk : integer_chunk_t;
|
|
357
|
+
variable offset, n : natural := 0;
|
|
358
|
+
begin
|
|
359
|
+
while offset < len loop
|
|
360
|
+
n := minimum(chunk_length, len - offset);
|
|
361
|
+
vpy_result_read_integers(chunk, offset, n);
|
|
362
|
+
result(offset to offset + n - 1) := chunk(0 to n - 1);
|
|
363
|
+
offset := offset + n;
|
|
364
|
+
end loop;
|
|
365
|
+
return result;
|
|
366
|
+
end;
|
|
367
|
+
|
|
368
|
+
impure function p_result_real_vector return real_vector is
|
|
369
|
+
constant len : natural := vpy_result_meta(0);
|
|
370
|
+
variable result : real_vector(0 to len - 1);
|
|
371
|
+
variable chunk : real_chunk_t;
|
|
372
|
+
variable offset, n : natural := 0;
|
|
373
|
+
begin
|
|
374
|
+
while offset < len loop
|
|
375
|
+
n := minimum(chunk_length, len - offset);
|
|
376
|
+
vpy_result_read_reals(chunk, offset, n);
|
|
377
|
+
result(offset to offset + n - 1) := chunk(0 to n - 1);
|
|
378
|
+
offset := offset + n;
|
|
379
|
+
end loop;
|
|
380
|
+
return result;
|
|
381
|
+
end;
|
|
382
|
+
|
|
383
|
+
impure function p_result_integer_array return integer_array_t is
|
|
384
|
+
constant len : natural := vpy_result_meta(0);
|
|
385
|
+
variable result : integer_array_t := new_3d(
|
|
386
|
+
width => vpy_result_meta(1),
|
|
387
|
+
height => vpy_result_meta(2),
|
|
388
|
+
depth => vpy_result_meta(3),
|
|
389
|
+
bit_width => vpy_result_meta(4),
|
|
390
|
+
is_signed => vpy_result_meta(5) /= 0
|
|
391
|
+
);
|
|
392
|
+
variable chunk : integer_chunk_t;
|
|
393
|
+
variable offset, n : natural := 0;
|
|
394
|
+
begin
|
|
395
|
+
while offset < len loop
|
|
396
|
+
n := minimum(chunk_length, len - offset);
|
|
397
|
+
vpy_result_read_integers(chunk, offset, n);
|
|
398
|
+
for idx in 0 to n - 1 loop
|
|
399
|
+
set(result, offset + idx, chunk(idx));
|
|
400
|
+
end loop;
|
|
401
|
+
offset := offset + n;
|
|
402
|
+
end loop;
|
|
403
|
+
return result;
|
|
404
|
+
end;
|
|
405
|
+
|
|
406
|
+
-----------------------------------------------------------------------------
|
|
407
|
+
-- Values transferred to Python
|
|
408
|
+
-----------------------------------------------------------------------------
|
|
409
|
+
impure function p_stage_array(arr : integer_array_t; operation : string) return integer is
|
|
410
|
+
constant len : natural := length(arr);
|
|
411
|
+
variable chunk : integer_chunk_t;
|
|
412
|
+
variable offset, n : natural := 0;
|
|
413
|
+
variable staged_id : integer;
|
|
414
|
+
begin
|
|
415
|
+
if not p_succeeded(
|
|
416
|
+
vpy_push_array(len, width(arr), height(arr), depth(arr), bit_width(arr), boolean'pos(is_signed(arr))),
|
|
417
|
+
operation
|
|
418
|
+
) then
|
|
419
|
+
return -1;
|
|
420
|
+
end if;
|
|
421
|
+
|
|
422
|
+
while offset < len loop
|
|
423
|
+
n := minimum(chunk_length, len - offset);
|
|
424
|
+
for idx in 0 to n - 1 loop
|
|
425
|
+
chunk(idx) := get(arr, offset + idx);
|
|
426
|
+
end loop;
|
|
427
|
+
if not p_succeeded(vpy_array_write(chunk, n), operation) then
|
|
428
|
+
return -1;
|
|
429
|
+
end if;
|
|
430
|
+
offset := offset + n;
|
|
431
|
+
end loop;
|
|
432
|
+
|
|
433
|
+
staged_id := vpy_stage;
|
|
434
|
+
if staged_id < 1 then
|
|
435
|
+
failure(python_logger, operation & " failed:" & LF & p_error_text);
|
|
436
|
+
return -1;
|
|
437
|
+
end if;
|
|
438
|
+
return staged_id;
|
|
439
|
+
end;
|
|
440
|
+
|
|
441
|
+
-----------------------------------------------------------------------------
|
|
442
|
+
-- The API
|
|
443
|
+
-----------------------------------------------------------------------------
|
|
444
|
+
procedure python_setup is
|
|
445
|
+
variable ok : boolean;
|
|
446
|
+
begin
|
|
447
|
+
ok := p_succeeded(vpy_setup, "python_setup");
|
|
448
|
+
end;
|
|
449
|
+
|
|
450
|
+
procedure python_cleanup is
|
|
451
|
+
variable ok : boolean;
|
|
452
|
+
begin
|
|
453
|
+
ok := p_succeeded(vpy_cleanup, "python_cleanup");
|
|
454
|
+
end;
|
|
455
|
+
|
|
456
|
+
procedure exec(code : string; session : python_session_t := default_session) is
|
|
457
|
+
variable ok : boolean;
|
|
458
|
+
begin
|
|
459
|
+
ok := p_exec(code, 0, p_exec_operation(session), session);
|
|
460
|
+
end;
|
|
461
|
+
|
|
462
|
+
impure function eval_integer(expr : string; session : python_session_t := default_session) return integer is
|
|
463
|
+
begin
|
|
464
|
+
if p_eval(expr, p_kind_integer, -1, p_eval_operation(expr, session), session) then
|
|
465
|
+
return vpy_result_integer;
|
|
466
|
+
end if;
|
|
467
|
+
return integer'low;
|
|
468
|
+
end;
|
|
469
|
+
|
|
470
|
+
impure function eval_real(expr : string; session : python_session_t := default_session) return real is
|
|
471
|
+
begin
|
|
472
|
+
if p_eval(expr, p_kind_real, -1, p_eval_operation(expr, session), session) then
|
|
473
|
+
return vpy_result_real;
|
|
474
|
+
end if;
|
|
475
|
+
return 0.0;
|
|
476
|
+
end;
|
|
477
|
+
|
|
478
|
+
impure function eval_integer_vector(
|
|
479
|
+
expr : string; session : python_session_t := default_session
|
|
480
|
+
) return integer_vector is
|
|
481
|
+
constant no_integers : integer_vector(0 downto 1) := (others => 0);
|
|
482
|
+
begin
|
|
483
|
+
if p_eval(expr, p_kind_integer_vector, -1, p_eval_operation(expr, session), session) then
|
|
484
|
+
return p_result_integer_vector;
|
|
485
|
+
end if;
|
|
486
|
+
return no_integers;
|
|
487
|
+
end;
|
|
488
|
+
|
|
489
|
+
impure function eval_real_vector(
|
|
490
|
+
expr : string; session : python_session_t := default_session
|
|
491
|
+
) return real_vector is
|
|
492
|
+
constant no_reals : real_vector(0 downto 1) := (others => 0.0);
|
|
493
|
+
begin
|
|
494
|
+
if p_eval(expr, p_kind_real_vector, -1, p_eval_operation(expr, session), session) then
|
|
495
|
+
return p_result_real_vector;
|
|
496
|
+
end if;
|
|
497
|
+
return no_reals;
|
|
498
|
+
end;
|
|
499
|
+
|
|
500
|
+
impure function eval_string(expr : string; session : python_session_t := default_session) return string is
|
|
501
|
+
begin
|
|
502
|
+
if p_eval(expr, p_kind_string, -1, p_eval_operation(expr, session), session) then
|
|
503
|
+
return p_result_string;
|
|
504
|
+
end if;
|
|
505
|
+
return "";
|
|
506
|
+
end;
|
|
507
|
+
end package body;
|