Embedded Python #
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 #
vvpcallsgpi_entry_pointwhich callsembed_init_python(see: VPI deep diveembed_init_python(defined inembed.cpp) loads the python library usingutils_dyn_openwhich uses the underlying system command dlopen. It also does the same thing for the embed implementation librarylibcocotb.so. symbols inlibcocotb.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
-
Then using
utils_dyn_sym()which uses underlying system command dlsym it takes a handle of a dynamic loaded shared object returned bydlopenalong 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
-
calls
_embed_init_pythonwhich exists inlibcocotb.socompiled from gpi_embed.cpp. The compilation can be seen incocotb_build_libs.libcocotb_sources = [os.path.join(share_lib_dir, "embed", "gpi_embed.cpp")]- The
_embedfunctions are the bridge from C++ to python, I believe.
-
it seems that all interaction between simulator and python must tunnel through
_embed_sim_event?