HardwareTeams.com - The #1 job board and blog for electrical and computer engineers


Embedded Python in Cocotb #

How embedded python works in cocotb.

!keep in mind The simulator loads a shared library which essentially “bootloads” cocotb. Important takeaway is that Python is embedded into C++, not the other way around. Python is not controlling the C++ code, the simulator is controlling the C++ and therefor controlling the embedded python.

Initialization #

  1. vvp calls gpi_entry_point which calls embed_init_python (see: VPI deep dive
  2. embed_init_python (defined in embed.cpp) loads the python library using utils_dyn_open which uses the underlying system command dlopen. It also does the same thing for the embed implementation library libcocotb.so. symbols in libcocotb.so:
> nm libcocotb.so
libcocotb.so
0000000000003ab8 s GCC_except_table2
                 U _PyArg_ParseTuple
                 U _PyErr_Print
                 U _PyEval_SaveThread
                 U _PyGILState_Ensure
                 U _PyGILState_Release
                 U _PyImport_ImportModule
                 U _PyList_New
                 U _PyList_SetItem
                 U _PyObject_CallFunction
                 U _PyObject_CallFunctionObjArgs
                 U _PyObject_CallMethod
                 U _PyObject_GetAttrString
                 U _PySys_SetArgvEx
                 U _PyUnicode_DecodeLocale
                 U _Py_DecRef
                 U _Py_DecodeLocale
                 U _Py_Finalize
                 U _Py_Initialize
                 U _Py_IsInitialized
                 U _Py_SetProgramName
                 U __Py_Dealloc
                 U __Unwind_Resume
0000000000008000 d __ZL4argv
0000000000009428 b __ZL7gtstate
0000000000009430 b __ZL8pEventFn
0000000000008008 d __ZL8progname
                 U __ZSt9terminatev
0000000000008428 b __ZZL24set_program_name_in_venvvE11venv_path_w
0000000000008028 b __ZZL24set_program_name_in_venvvE9venv_path
0000000000003738 t ___clang_call_terminate
                 U ___cxa_begin_catch
                 U ___error
                 U ___gxx_personality_v0
0000000000002dac T __embed_init_python
0000000000003140 T __embed_sim_cleanup
0000000000003744 T __embed_sim_event
0000000000003264 T __embed_sim_init
                 U _exit
                 U _getenv
                 U _getpid
                 U _gpi_log
                 U _is_python_context
                 U _py_gpi_logger_finalize
                 U _py_gpi_logger_initialize
                 U _sleep
                 U _strlen
                 U _strncat
                 U _strncpy
                 U _strtoul
                 U _wcsncpy
  1. Then using utils_dyn_sym() which uses underlying system command dlsym it takes a handle of a dynamic loaded shared object returned by dlopen along with a null-terminated symbol name, and returns the address where that symbol is loaded into memory. It basically tells the program where to find the following functions

    • _embed_init_python
    • _embed_sim_cleanup
    • _embed_sim_init
    • _embed_sim_event
  2. calls _embed_init_python which exists in libcocotb.so compiled from gpi_embed.cpp. The compilation can be seen in cocotb_build_libs.

    • libcocotb_sources = [os.path.join(share_lib_dir, "embed", "gpi_embed.cpp")]
    • The _embed functions are the bridge from C++ to python, I believe.
  3. it seems that all interaction between simulator and python must tunnel through _embed_sim_event?

HardwareTeams.com Copyright © 2024
comments powered by Disqus