Microblaze RPC¶
The PYNQ Microblaze infrastructure is built on top of a remote procedure call (RPC) layer which is responsible for forwarding function calls from the Python environment to the Microblaze and handling all data transfer.
Supported Function Signatures¶
The RPC layer supports a subset of the C programming language for interface functions, although any functions may be used internally within the Microblaze program. Any function which does not conform to these requirements will be ignored. The limitations are:
- No
struct
orunion
for either parameters or return types. - No returning of pointer types
- No pointers to pointers
Data Transfer¶
All return values are passed back to Python through copying. The transfer of function arguments depends on the type used. For a given non-void primitive the following semantics:
- Non-pointer types are copied from PYNQ to the microblaze
- Const pointer types are copied from Python to the Microblaze
- Non-const pointer types are copied from Python to the Microblaze and then copied back after completion of the function.
The timeline of the execution of the function can be seen below:
The Python struct
module is used to convert the Python type passed
to the function into the appropriately sized integer or floating point
value for the Microblaze. Out of range values will result in an
exception being raised and the Microblaze function not running. Arrays
of types are treated similarly with the struct
module used to
perform the conversion from an array of Python types to the C array. For
non-const arrays, the array is updated in place so that the return
values are available to the caller. The only exception to these
conversion rules are char
and const char
pointers which are
optimised for Python bytearray
and bytes
types. Note that
calling a function with a non-const char*
argument with a bytes
object will result in an error because bytes
objects are read-only.
This will caught prior to the Microblaze function being called.
Long-running Functions¶
For non-void return functions, the Python functions are synchronous and
will wait for the C function to finish prior to returning to the caller.
For functions that return void then the function is called
asynchronously and the Python function will return immediately. This
entails long-running, independent functions to run on the Microblaze
without blocking the Python thread. While the function is running, no
other functions can be called unless the long-running process frequently
calls yield
(from yield.h
) to allow the RPC runtime to service
requests. Please note - there is no multi-threading available inside the
Microblaze so attempting to run two long-running processes
simultaneously will result in only one executing regardless of the use
of yield
.
Typedefs¶
The RPC engine fully supports typedefs and provides an additional
mechanism to allow for C functions to appear more like Python classes.
The RPC layer recognises the idiom where the name of a typedef is used
as the prefix for a set of function names. Taking an example from the
PYNQ Microblaze library, the i2c
typedef has corresponding functions
i2c_read
and i2c_write
which take an i2c
type as the first
parameter. With this idiom the RPC creates a new class called i2c
which has read
and write
methods. Any C functions returning an
i2c
typedef now return an instance of this class. For this
conversion to be done, the following three properties must hold:
- The typedef is of a primitive type
- There is at least one function returning the typedef
- There is at least one function named according to the pattern