Initial commit
[tidl/tidl-api.git] / tinn_api / src / executor.cpp
1 #include <assert.h>
2 #include "executor.h"
3 #include "executor_impl.h"
4 #include "parameters.h"
5 #include "util.h"
6 #include "trace.h"
9 using namespace tidl;
11 using std::unique_ptr;
13 Executor::Executor(DeviceType core_type, const DeviceIds& ids,
14                    const Configuration& configuration)
15 {
16     pimpl_m = unique_ptr<ExecutorImpl>
17               { new ExecutorImpl(core_type, ids) };
18     pimpl_m->Initialize(configuration);
19 }
23 // Pointer to implementation idiom: https://herbsutter.com/gotw/_100/:
24 // Both unique_ptr and shared_ptr can be instantiated with an incomplete type
25 // unique_ptr's destructor requires a complete type in order to invoke delete
26 // By writing it yourself in the implementation file, you force it to be
27 // defined in a place where impl is already defined, and this successfully
28 // prevents the compiler from trying to automatically generate the destructor
29 // on demand in the caller’s code where impl is not defined.
30 Executor::~Executor() = default;
32 uint32_t Executor::GetNumDevicesSupportingTIDL(DeviceType device_type)
33 {
34     return Device::GetNumDevicesSupportingTIDL(device_type);
35 }
37 ExecutorImpl::ExecutorImpl(DeviceType core_type, const DeviceIds& ids):
38     configuration_m(),
39     shared_networkparam_heap_m(nullptr, &__free_ddr),
40     device_ids_m(ids),
41     core_type_m(core_type)
42 {
43     std::string name;
44     if (core_type_m == DeviceType::DSP)
45         name  = "ocl_wrapper.out";
46     else if (core_type_m == DeviceType::DLA)
47         name = STRING(SETUP_KERNEL) ";" STRING(INIT_KERNEL) ";" STRING(PROCESS_KERNEL) ";" STRING(CLEANUP_KERNEL);
49     device_m = Device::Create(core_type_m, ids, name);
51 }
54 const ExecutionObjects& Executor::GetExecutionObjects() const
55 {
56     return pimpl_m->execution_objects_m;
57 }
59 bool ExecutorImpl::Initialize(const Configuration& configuration)
60 {
61     configuration_m = configuration;
63     // Allocate, initialize TIDL_CreateParams object
64     up_malloc_ddr<TIDL_CreateParams> shared_createparam(
65                                             malloc_ddr<TIDL_CreateParams>(),
66                                             &__free_ddr);
67     InitializeNetworkCreateParam(shared_createparam.get());
69     // Read network from file into network struct in TIDL_CreateParams
70     sTIDL_Network_t *net = &(shared_createparam.get())->net;
72     bool status = ReadBinary(configuration_m.netBinFile,
73                              reinterpret_cast<char *>(net),
74                              sizeof(sTIDL_Network_t));
75     assert(status != false);
77     //TODO: Why is this set here?
78     net->interElementSize = 4;
80     // Call a setup kernel to allocate and fill network parameters
81     InitializeNetworkParams(shared_createparam.get());
83     const ArgInfo create_arg(shared_createparam.get(),
84                              sizeof(TIDL_CreateParams));
85     const ArgInfo param_heap_arg(shared_networkparam_heap_m.get(),
86                                  configuration_m.PARAM_HEAP_SIZE);
87     for (auto ids : device_ids_m)
88     {
89         uint8_t index = static_cast<uint8_t>(ids);
90         execution_objects_m.push_back(
91              unique_ptr<ExecutionObject>
92              {new ExecutionObject(device_m.get(), index,
93                                   create_arg, param_heap_arg,
94                                   configuration_m.EXTMEM_HEAP_SIZE)} );
95     }
97     for (auto &eo : execution_objects_m)
98         eo->RunAsync(ExecutionObject::CallType::INIT);
100     for (auto &eo : execution_objects_m)
101         eo->Wait(ExecutionObject::CallType::INIT);
103     return true;
107 bool ExecutorImpl::InitializeNetworkParams(TIDL_CreateParams *cp)
109     // Determine size of network parameters buffer, allocate it
110     size_t networkparam_size =
111                         GetBinaryFileSize(configuration_m.paramsBinFile);
113     up_malloc_ddr<char> networkparam(malloc_ddr<char>(networkparam_size),
114                                 &__free_ddr);
116     // Read network parameters from bin file into buffer
117     bool status = ReadBinary(configuration_m.paramsBinFile,
118                              networkparam.get(),
119                              networkparam_size);
120     assert(status != false);
122     // Allocate a buffer for passing parameters to the kernel
123     up_malloc_ddr<OCL_TIDL_SetupParams> setupParams(
124                                             malloc_ddr<OCL_TIDL_SetupParams>(),
125                                             &__free_ddr);
127     setupParams->enableTrace = OCL_TIDL_TRACE_OFF;
128     setupParams->networkParamHeapSize = configuration_m.PARAM_HEAP_SIZE;
129     setupParams->noZeroCoeffsPercentage = configuration_m.noZeroCoeffsPercentage;
130     setupParams->sizeofTIDL_CreateParams = sizeof(TIDL_CreateParams);
131     setupParams->offsetofNet = offsetof(TIDL_CreateParams, net);
133     // Allocate buffer for a network parameter heap. Used by the setup
134     // kernel to allocate and initialize network parameters for the layers
135     shared_networkparam_heap_m.reset(malloc_ddr<char>(setupParams->networkParamHeapSize));
137     KernelArgs args = { ArgInfo(cp, sizeof(TIDL_CreateParams)),
138                         ArgInfo(networkparam.get(), networkparam_size),
139                         ArgInfo(shared_networkparam_heap_m.get(),
140                                 setupParams->networkParamHeapSize),
141                         ArgInfo(setupParams.get(),
142                                 sizeof(OCL_TIDL_SetupParams)) };
144     // Execute kernel on first available device in the Executor
145     uint8_t id = static_cast<uint8_t>(*(device_ids_m.cbegin()));
146     unique_ptr<Kernel> K {new Kernel(device_m.get(), STRING(SETUP_KERNEL),
147                                      args, id)};
148     K->RunAsync();
149     K->Wait();
151     if (setupParams->errorCode != OCL_TIDL_SUCCESS)
152         throw Exception(setupParams->errorCode,
153                         __FILE__, __FUNCTION__, __LINE__);
155     return status;
159 void ExecutorImpl::Cleanup()
161     for (auto &eo : execution_objects_m)
162         eo->RunAsync(ExecutionObject::CallType::CLEANUP);
164     for (auto &eo : execution_objects_m)
165         eo->Wait(ExecutionObject::CallType::CLEANUP);
169 void ExecutorImpl::InitializeNetworkCreateParam(TIDL_CreateParams *CP)
171     CP->currCoreId           = tidl::internal::CURR_CORE_ID;
172     CP->currLayersGroupId    = tidl::internal::CURR_LAYERS_GROUP_ID;
173     CP->l1MemSize            = tidl::internal::DMEM0_SIZE;
174     CP->l2MemSize            = tidl::internal::DMEM1_SIZE;
175     CP->l3MemSize            = tidl::internal::OCMC_SIZE;
177     CP->quantHistoryParam1   = tidl::internal::QUANT_HISTORY_PARAM1;
178     CP->quantHistoryParam2   = tidl::internal::QUANT_HISTORY_PARAM2;
179     CP->quantMargin          = tidl::internal::QUANT_MARGIN;
180     CP->optimiseExtMem       = TIDL_optimiseExtMemL1;
183 Exception::Exception(const std::string& error, const std::string& file,
184                      const std::string& func, uint32_t line_no)
187     message_m = "TIDL Error: [";
188     message_m += file;
189     message_m += ", ";
190     message_m += func;
191     message_m += ", ";
192     message_m += std::to_string(line_no);
193     message_m += "]: ";
194     message_m += error;
197 Exception::Exception(int32_t errorCode, const std::string& file,
198                      const std::string& func, uint32_t line_no)
200     message_m = "TIDL Error: [";
201     message_m += file;
202     message_m += ", ";
203     message_m += func;
204     message_m += ", ";
205     message_m += std::to_string(line_no);
206     message_m += "]: ";
208     if (errorCode == OCL_TIDL_ERROR)
209         message_m += "";
210     else if (errorCode == OCL_TIDL_ALLOC_FAIL)
211         message_m += "Allocation failed on device";
212     else if (errorCode == OCL_TIDL_MEMREC_ALLOC_FAIL)
213         message_m += "Memrec allocation failed on device";
214     else if (errorCode == OCL_TIDL_PROCESS_FAIL)
215         message_m += "Process call failed on device";
216     else if (errorCode == OCL_TIDL_CREATE_PARAMS_MISMATCH)
217         message_m += "TIDL_CreateParams definition inconsistent across host"
218                      "and device.";
219     else
220         message_m += std::to_string(errorCode);
224 const char* Exception::what() const noexcept
226     return message_m.c_str();