Functions

Before proceeding with this section, make sure that you are already familiar with the basics of binding functions and classes, as explained in First steps and Object-oriented code. The following guide is applicable to both free and member functions, i.e. methods in Python.

Return value policies

Python and SystemVerilog use fundamentally different ways of managing the memory and lifetime of objects managed by them. This can lead to issues when creating bindings for functions that return a non-trivial type. When non-trivial type returned SystemVerilog should manage the object life time and deallocate the memory occupied by the object with py_object::delete() when the object is no longer needed.

Return value policies are tricky, and it’s very important to get them right. Just to illustrate what can go wrong, consider the following simple example:

//equivalent to: from decimal import Decimal
py_object Decimal = py_module::import_("decimal").attr("Decimal").obtain();
py_object decimal_exp = Decimal.attr("exp");

// Compute the e^n for n=0..4
for (int n = 0; n < 5; n++) begin
    py_object d = Decimal.call(py::int_(n));
    py::print(py::str_("Result: "), decimal_exp.call(d));
end

What’s going on here? When decimal_exp.call(d) is called and the result object passed to py::print() function, the handler the result of decimal_exp.call(d) no longer available. Therefore it is not possible to access the result of decimal_exp.call(d) and deallocate the memory occupied by the object. The same issue occurs for the object d. The the d.delete() function not called to deallocate the memory occupied by the object during the loop. Non trivial type objects should be deallocated by calling the py_object::delete() function. The Python garbage collector will not deallocate the memory occupied by the this objects since the object reference count is not zero.

The proper way to write to the above code is to deallocate the memory occupied by the object d and the result of decimal_exp.call(d).

//equivalent to: from decimal import Decimal
py_object Decimal = py_module::import_("decimal").attr("Decimal").obtain();
py_object decimal_exp = Decimal.attr("exp");

// Compute the e^n for n=0..4
for (int n = 0; n < 5; n++) begin
    py_object d = Decimal.call(py::int_(n));
    py_object result = decimal_exp.call(d);
    py::print(py::str_("Result: "), result);
    result.delete();
    d.delete();
end

Python objects as arguments

PyStim exposes all major Python types using thin SystemVerilog wrapper classes. These wrapper classes can also be used as parameters of functions in bindings, which makes it possible to directly work with native Python types on the SystemVerilog side. For instance, the following statement iterates over a Python dict:

function void print_dict(py::py_dict dict);
    /* Easily interact with Python types */
    iterator it = students_dict.get_iterator();
    while(it.has_next())begin
        py_pair p = it.next().cast_dict_pair();
        py_object key = p.get_key();
        py_object value = p.get_value();
        $display("Key: %s, Value: %s", key.cast_string().get_value(),
                value.cast_uint().get_value());

    end
endfunction

Note

Currently, the SystemVerilog dict wrapper class supports only keys of type string.

For more information on using Python objects in SystemVerilog, see Python SystemVerilog interface.

Accepting *args and **kwargs

Python provides a useful mechanism to define functions that accept arbitrary numbers of arguments and keyword arguments:

def generic(*args, **kwargs):
    ...  # do something with args and kwargs

To call the Python function with args and kwargs, use SystemVerilog named arguments mapping:

py_tuple args = ...;
py_dict kwargs = ...;
... // do something with args and kwargs
some_attribute.call(.args(args), .kwargs(kwargs));

The class py_args derives from py_tuple and py_kwargs derives from py_dict.

You may also use just one or the other, and may combine these with other arguments. Note, however, that args and kwargs must always be named mapped arguments.

A demonstration of args and kwargs is available in examples/misc/test_args_and_kwargs.sv.