If you've ever struggled with DPI-C wrappers just to reuse your Python libraries in a SystemVerilog testbench, there's a much easier way — and it's called PyStim.

As someone working in RTL design, I've often used Python to rapidly prototype RTL modules because it's fast, flexible, and developer-friendly. But integrating those Python models into a SystemVerilog verification environment traditionally required writing cumbersome C wrappers and DPI-C glue code.

Why You’ll Love PyStim

  • Zero C/C++ Glue

    • No hand-rolled wrappers or autogenerated stubs—just point PyStim at your Python module and go.
  • True Object Accessibility

    • Instantiate Python classes, invoke methods, and pass data back and forth as native SystemVerilog objects.
  • Inline Python Execution

    • Run arbitrary Python scripts or snippets directly from your RTL simulator.

What You Need

  • Python ≥ 3.7
  • A SystemVerilog Simulator: QuestaSim, VCS, Xcelium, or Verilator ≥ 5.034
  • Linux Host: RHEL 7/8/9 or Ubuntu ≥ 22.04

Example

Python model (counter.py):

#counter.py
class Counter:
    def __init__(self, initial=0):
        self.value = initial

    def inc(self):
        self.value += 1
        return self.value

SystemVerilog integration:

import pystim_pkg::*;

module simple_calc();

  typedef pystim_pkg::pystim py;

  initial begin
    // Python interpreter initialization
    py::initialize_interpreter();

    begin
      py_object result; 
      begin
        // import Counter from counter
        automatic py_object Counter = py_module::import_("counter").attr("Counter");
        // Directly instantiate Python Counter object
        automatic py_object cnt = Counter.call(py::int_(0));

         // Call Python method without DPIC wrappers
        repeat(3)begin
          result = cnt.attr("inc").call();
          $display("Cnt: %0d", result.cast_int().get_value());
        end
      end
    end

    // Finalize PyStim
    py::finalize_interpreter();
  end

endmodule

Running this testbench will directly interact with the Python object, yielding output:

# Cnt: 1
# Cnt: 2
# Cnt: 3

Executing Arbitrary Python Code

PyStim can directly run any Python script or code snippet.

...
automatic py_dict globals = py::globals();
automatic py_dict locals = py_dict::create_empty();

locals.set(py::string_("name"),py::string_("Python"));
py::exec("print('Hello from {}!'.format(name))", globals, locals);
...

The inherent simplicity makes it much easier to reuse Python libraries and achieve rapid prototyping.

Final Thoughts:

The reduced integration complexity offered by PyStim has substantially improved my workflow. By enabling direct Python interaction within SystemVerilog, it accelerates both testing and development, making it a powerful and efficient tool for tackling complex RTL design & verification tasks.