Embedding the interpreter

PyStim mainly focuses on extending SystemVerilog using Python, by embedding the Python interpreter into a SystemVerilog program. This allows the SystemVerilog program to execute Python code and interact with Python objects. All of the other documentation pages still apply here, so refer to them for general PyStim usage.

Getting started

A basic simulation with an embedded interpreter can be created with just a few lines of bash code and the pystim_pkg package methods, as shown below. For more information, see Build systems.

source ../../scripts/environment.sh
./run.sh questa

The essential structure of the hello_world.sv file looks like this:

import pystim_pkg::*;

module hello_world();
    typedef pystim py;

    initial begin
        py::initialize_interpreter();
        py::print(py::str_("Hello world."));
        py::finalize_interpreter();
    end
endmodule

The interpreter must be initialized before using any Python, which includes all the functions and classes in PyStim. The methods class initialize_interpreter(), and finalize_interpreter() are used to manage interpreter lifetime. After the finalize_interpreter() call, the Python interpreter shuts down and clears its memory. No Python functions can be called after this.

Importing modules

Python modules can be imported using py_module::import_():

py_module sys = py_module::import_("sys");
py::print(sys.attr("path").obtain());

For convenience, the current working directory is included in sys.path when embedding the interpreter. This makes it easy to import local Python files:

"""calc.py located in the working directory"""


def add(i, j):
    return i + j
begin
    py_module calc = py_module::import_("add_numbers");
    py_object res = calc.attr("add").call(py::int_(1), py::float_(2.2));
    int n = res.cast_int().get_value();
    assert (n == 3.2)
end

Interpreter lifetime

The Python interpreter starts up with initialize_interpreter and shuts down when finalize_interpreter is called. HDL simulation permits only one pair of initialize_interpreter and finalize_interpreter function calls. After this, creating a new instance of interpreter not possible. The initialize_interpreter / finalize_interpreter methods can be used anywhere in the SystemVerilog code to set the state of the interpreter at any time.

Warning

Starting two python interpreters is a fatal error. So is calling initialize_interpreter for a second time after the interpreter has already been initialized will case a fatal error. The same applies to calling finalize_interpreter for a second time after the interpreter has already been finalized.

Do not use the raw CPython API functions initialize_interpreter and finalize_interpreter as these do not properly handle the lifetime of PyStim’s internal data.

Restarting the interpter

When using the HDL simulator GUI (intractive mode) for mixed-language (HDL and C/Python) simulations, it’s essential to understand how the simulation state for HDL and C/Python code are managed during a simulation restart in the already running context.

In HDL simulators, restarting the simulation in the GUI primarily affects the HDL side of the simulation. It resets the state of the HDL simulation, including all signal values, registers, and memories to their initial state as defined at simulation zero time. However, the state of the C/Python code used in the simulation (for instance, through DPI, VPI, or PLI) is not automatically reset by this action.

While the HDL simulation is restarted in already running context, PyStim library does automatically restart the Python interpreter. However, this may not apply to third-party extension Python modules.The issue is that Python itself cannot completely unload extension modules and there are several caveats with regard to interpreter restarting. In short, not all memory may be freed, either due to Python reference cycles or user-created global data. All the details can be found in the CPython documentation.

Recommendation for Developers:
  • Plan Initialization and Reset: Ensure your Python code includes well-defined

initialization and reset functions that can be called from HDL.
  • Simulation Hooks: Use simulator-specific mechanisms (e.g., callbacks or $restart commands) to integrate the reset process.

  • Testing: Regularly test the behavior of your mixed-language simulation during restarts to verify proper synchronization between HDL and Python states.

By understanding this distinction and explicitly managing the Python code state during HDL simulation restarts, you can maintain consistency and avoid unintended simulation behavior.

Sub-interpreter support

Creating multiple copies of interpreter is not possible because it represents the main Python interpreter. Sub-interpreters are something different and they do permit the existence of multiple interpreters. This is an advanced feature of the CPython API and should be handled with care. PyStim does not currently offer a interface for sub-interpreters, so refer to the CPython documentation for all the details regarding this feature.