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 #
vvp
callsgpi_entry_point
which callsembed_init_python
(see: VPI deep diveembed_init_python
(defined inembed.cpp
) loads the python library usingutils_dyn_open
which 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 bydlopen
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
-
calls
_embed_init_python
which exists inlibcocotb.so
compiled 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
_embed
functions are the bridge from C++ to python, I believe.
-
it seems that all interaction between simulator and python must tunnel through
_embed_sim_event
?