e16f6d0eca7132a9828b13d9c2deeabef825ca23
[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 tinn;
11 using std::unique_ptr;
13 Executor::Executor(DeviceType core_type, const DeviceIds& ids,
14                    const Configuration& configuration, int layers_group_id)
15 {
16     pimpl_m = unique_ptr<ExecutorImpl>
17               { new ExecutorImpl(core_type, ids, layers_group_id) };
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::GetNumDevices(DeviceType device_type)
33 {
34     return Device::GetNumDevices(device_type);
35 }
37 #define STRING(S)  XSTRING(S)
38 #define XSTRING(S) #S
39 std::string Executor::GetAPIVersion()
40 {
41     static std::string version = STRING(_BUILD_VER);
42     version += ".";
43     version += STRING(_BUILD_SHA);
44     return version;
45 }
48 ExecutorImpl::ExecutorImpl(DeviceType core_type, const DeviceIds& ids,
49                            int layers_group_id):
50     configuration_m(),
51     shared_networkparam_heap_m(nullptr, &__free_ddr),
52     device_ids_m(ids),
53     core_type_m(core_type),
54     layers_group_id_m(layers_group_id)
55 {
56     std::string name;
57     if (core_type_m == DeviceType::DSP)
58         name  = "";
59     else if (core_type_m == DeviceType::DLA)
60         name = STRING(SETUP_KERNEL) ";" STRING(INIT_KERNEL) ";" STRING(PROCESS_KERNEL) ";" STRING(CLEANUP_KERNEL);
62     device_m = Device::Create(core_type_m, ids, name);
63 }
66 const ExecutionObjects& Executor::GetExecutionObjects() const
67 {
68     return pimpl_m->execution_objects_m;
69 }
71 bool ExecutorImpl::Initialize(const Configuration& configuration)
72 {
73     configuration_m = configuration;
75     // Allocate, initialize TIDL_CreateParams object
76     up_malloc_ddr<TIDL_CreateParams> shared_createparam(
77                                             malloc_ddr<TIDL_CreateParams>(),
78                                             &__free_ddr);
79     InitializeNetworkCreateParam(shared_createparam.get(), configuration);
81     // Read network from file into network struct in TIDL_CreateParams
82     sTIDL_Network_t *net = &(shared_createparam.get())->net;
84     bool status = ReadBinary(configuration_m.netBinFile,
85                              reinterpret_cast<char *>(net),
86                              sizeof(sTIDL_Network_t));
87     assert(status != false);
89     //TODO: Why is this set here?
90     net->interElementSize = 4;
92     // Force to run full network if runFullNet is set
93     if (configuration.runFullNet)
94     {
95         for (int i = 0; i < net->numLayers; i++)
96             if (net->TIDLLayers[i].layerType != TIDL_DataLayer)
97                 net->TIDLLayers[i].layersGroupId = layers_group_id_m;
98     }
100     // Call a setup kernel to allocate and fill network parameters
101     InitializeNetworkParams(shared_createparam.get());
103     const ArgInfo create_arg(shared_createparam.get(),
104                              sizeof(TIDL_CreateParams));
105     const ArgInfo param_heap_arg(shared_networkparam_heap_m.get(),
106                                  configuration_m.PARAM_HEAP_SIZE);
107     for (auto ids : device_ids_m)
108     {
109         uint8_t index = static_cast<uint8_t>(ids);
110         execution_objects_m.push_back(
111              unique_ptr<ExecutionObject>
112              {new ExecutionObject(device_m.get(), index,
113                                   create_arg, param_heap_arg,
114                                   configuration_m.EXTMEM_HEAP_SIZE,
115                                   configuration_m.enableInternalInput)} );
116     }
118     for (auto &eo : execution_objects_m)
119         eo->RunAsync(ExecutionObject::CallType::INIT);
121     for (auto &eo : execution_objects_m)
122         eo->Wait(ExecutionObject::CallType::INIT);
124     return true;
128 bool ExecutorImpl::InitializeNetworkParams(TIDL_CreateParams *cp)
130     // Determine size of network parameters buffer, allocate it
131     size_t networkparam_size =
132                         GetBinaryFileSize(configuration_m.paramsBinFile);
134     up_malloc_ddr<char> networkparam(malloc_ddr<char>(networkparam_size),
135                                 &__free_ddr);
137     // Read network parameters from bin file into buffer
138     bool status = ReadBinary(configuration_m.paramsBinFile,
139                              networkparam.get(),
140                              networkparam_size);
141     assert(status != false);
143     // Allocate a buffer for passing parameters to the kernel
144     up_malloc_ddr<OCL_TIDL_SetupParams> setupParams(
145                                             malloc_ddr<OCL_TIDL_SetupParams>(),
146                                             &__free_ddr);
148     setupParams->enableTrace = OCL_TIDL_TRACE_OFF;
149     setupParams->networkParamHeapSize = configuration_m.PARAM_HEAP_SIZE;
150     setupParams->noZeroCoeffsPercentage = configuration_m.noZeroCoeffsPercentage;
151     setupParams->sizeofTIDL_CreateParams = sizeof(TIDL_CreateParams);
152     setupParams->offsetofNet = offsetof(TIDL_CreateParams, net);
154     // Allocate buffer for a network parameter heap. Used by the setup
155     // kernel to allocate and initialize network parameters for the layers
156     shared_networkparam_heap_m.reset(malloc_ddr<char>(setupParams->networkParamHeapSize));
158     KernelArgs args = { ArgInfo(cp, sizeof(TIDL_CreateParams)),
159                         ArgInfo(networkparam.get(), networkparam_size),
160                         ArgInfo(shared_networkparam_heap_m.get(),
161                                 setupParams->networkParamHeapSize),
162                         ArgInfo(setupParams.get(),
163                                 sizeof(OCL_TIDL_SetupParams)) };
165     // Execute kernel on first available device in the Executor
166     uint8_t id = static_cast<uint8_t>(*(device_ids_m.cbegin()));
167     unique_ptr<Kernel> K {new Kernel(device_m.get(), STRING(SETUP_KERNEL),
168                                      args, id)};
169     K->RunAsync();
170     K->Wait();
172     if (setupParams->errorCode != OCL_TIDL_SUCCESS)
173         throw Exception(setupParams->errorCode,
174                         __FILE__, __FUNCTION__, __LINE__);
176     return status;
180 void ExecutorImpl::Cleanup()
182     for (auto &eo : execution_objects_m)
183         eo->RunAsync(ExecutionObject::CallType::CLEANUP);
185     for (auto &eo : execution_objects_m)
186         eo->Wait(ExecutionObject::CallType::CLEANUP);
190 void ExecutorImpl::InitializeNetworkCreateParam(TIDL_CreateParams *CP,
191                                           const Configuration& configuration)
193     CP->currCoreId           = layers_group_id_m;
194     CP->currLayersGroupId    = layers_group_id_m;
195     CP->l1MemSize            = tinn::internal::DMEM0_SIZE;
196     CP->l2MemSize            = tinn::internal::DMEM1_SIZE;
197     CP->l3MemSize            = tinn::internal::OCMC_SIZE;
199     CP->quantHistoryParam1   = tinn::internal::QUANT_HISTORY_PARAM1;
200     CP->quantHistoryParam2   = tinn::internal::QUANT_HISTORY_PARAM2;
201     CP->quantMargin          = tinn::internal::QUANT_MARGIN;
202     CP->optimiseExtMem       = TIDL_optimiseExtMemL1;
205 Exception::Exception(const std::string& error, const std::string& file,
206                      const std::string& func, uint32_t line_no)
209     message_m = "TIDL Error: [";
210     message_m += file;
211     message_m += ", ";
212     message_m += func;
213     message_m += ", ";
214     message_m += std::to_string(line_no);
215     message_m += "]: ";
216     message_m += error;
219 Exception::Exception(int32_t errorCode, const std::string& file,
220                      const std::string& func, uint32_t line_no)
222     message_m = "TIDL Error: [";
223     message_m += file;
224     message_m += ", ";
225     message_m += func;
226     message_m += ", ";
227     message_m += std::to_string(line_no);
228     message_m += "]: ";
230     if (errorCode == OCL_TIDL_ERROR)
231         message_m += "";
232     else if (errorCode == OCL_TIDL_ALLOC_FAIL)
233         message_m += "Allocation failed on device";
234     else if (errorCode == OCL_TIDL_MEMREC_ALLOC_FAIL)
235         message_m += "Memrec allocation failed on device";
236     else if (errorCode == OCL_TIDL_PROCESS_FAIL)
237         message_m += "Process call failed on device";
238     else if (errorCode == OCL_TIDL_CREATE_PARAMS_MISMATCH)
239         message_m += "TIDL_CreateParams definition inconsistent across host"
240                      "and device.";
241     else
242         message_m += std::to_string(errorCode);
246 const char* Exception::what() const noexcept
248     return message_m.c_str();