Added Python 3 bindings for TIDL API
[tidl/tidl-api.git] / tidl_api / src / pybind_executor.cpp
1 /******************************************************************************
2  * Copyright (c) 2018-2018 Texas Instruments Incorporated - http://www.ti.com/
3  *  All rights reserved.
4  *
5  *  Redistribution and use in source and binary forms, with or without
6  *  modification, are permitted provided that the following conditions are met:
7  *      * Redistributions of source code must retain the above copyright
8  *        notice, this list of conditions and the following disclaimer.
9  *      * Redistributions in binary form must reproduce the above copyright
10  *        notice, this list of conditions and the following disclaimer in the
11  *        documentation and/or other materials provided with the distribution.
12  *      * Neither the name of Texas Instruments Incorporated nor the
13  *        names of its contributors may be used to endorse or promote products
14  *        derived from this software without specific prior written permission.
15  *
16  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
26  *  THE POSSIBILITY OF SUCH DAMAGE.
27  *****************************************************************************/
29 /*! \file pybind_executor.cpp */
31 // Requires https://github.com/pybind/pybind11, branch v2.2
32 // References:
33 // 1. https://pybind11.readthedocs.io/en/stable/advanced/functions.html#return-value-policies
34 // 2. https://pybind11.readthedocs.io/en/stable/advanced/pycpp/numpy.html#buffer-protocol
35 // 3. https://www.python.org/dev/peps/pep-0008/
37 #include "pybind_common.h"
39 void AllocateMemory(const vector<ExecutionObject *>& eos);
40 void AllocateMemory(const vector<ExecutionObjectPipeline *>& eos);
41 void FreeMemory(const vector<ExecutionObject *>& eos);
42 void FreeMemory(const vector<ExecutionObjectPipeline *>& eos);
44 #define STRING(S)  XSTRING(S)
45 #define XSTRING(S) #S
47 PYBIND11_MAKE_OPAQUE(EO);
49 // Class, method names follow PEP8, Style Guide for Python Code (Reference #3)
50 PYBIND11_MODULE(tidl, m)
51 {
52     m.doc() = std::string("TIDL API Python bindings ") + STRING(_BUILD_VER);
53     m.attr("__version__") = STRING(_BUILD_VER);
55     register_exception<Exception>(m, "TidlError");
57     enum_<DeviceType>(m, "DeviceType")
58         .value("DSP", DeviceType::DSP)
59         .value("EVE", DeviceType::EVE);
61     enum_<DeviceId>(m, "DeviceId")
62         .value("ID0", DeviceId::ID0)
63         .value("ID1", DeviceId::ID1)
64         .value("ID2", DeviceId::ID2)
65         .value("ID3", DeviceId::ID3);
67     init_configuration(m);
68     init_eo(m);
69     init_eop(m);
71     // For an explanation of return_value_policy, see Reference #1
72         class_<Executor>(m, "Executor")
73         .def(init<DeviceType, std::set<DeviceId>, Configuration, int>())
75         .def("get_num_execution_objects", &Executor::GetNumExecutionObjects,
76              "Returns number of ExecutionObjects created by this Executor")
78         .def_static("get_num_devices", &Executor::GetNumDevices,
79              "Returns number of devices of the specified type\n"
80              "available for TI DL offload")
82         .def_static("get_api_version", &Executor::GetAPIVersion)
84         .def("at", &Executor::operator[], return_value_policy::reference,
85             "Returns the ExecutionObject at the specified index");
87     // Used to expose the EO's internal input and output buffers to the
88     // python application using the Python buffer protocol (Reference #2)
89     class_<ArgInfo>(m, "ArgInfo", buffer_protocol())
90         .def_buffer([](ArgInfo& ai) -> buffer_info
91                 {
92                     return buffer_info(
93                             ai.ptr(),
94                             sizeof(char),
95                             pybind11::format_descriptor<char>::format(),
96                             1,
97                             {ai.size()},
98                             {1}
99                            );
100                 })
101         .def("size", &ArgInfo::size, "Size of the buffer in bytes")
102         .def("__repr__",
103              [](const ArgInfo& ai)
104              {
105                 std::stringstream ss;
106                 ss << "<ArgInfo: ptr= " << ai.ptr() << " size= " << ai.size()
107                    << ">";
108                 return ss.str();
109              });
111     // Helper functions to allocate memory from Python
112     m.def("allocate_memory",
113           (void (*)(const vector<EO *>&)) &AllocateMemory,
114           "Allocate input and output buffers for all ExecutionObjects");
116     m.def("free_memory",
117            (void (*)(const vector<EO *>&)) &FreeMemory,
118           "Free input and output buffers of all ExecutionObjects");
120     m.def("allocate_memory",
121           (void (*)(const vector<EOP *>&)) &AllocateMemory,
122           "Allocate input and output buffers for all ExecutionObjectPipelines");
124     m.def("free_memory",
125            (void (*)(const vector<EOP *>&)) &FreeMemory,
126           "Free input and output buffers of all ExecutionObjectPipelines");