2 * Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include "TrixBackend.h"
21 #if defined(__linux__)
23 using namespace ::npud::backend::trix;
25 TrixBackend *allocate() { return new TrixBackend(); }
27 void deallocate(TrixBackend *trix) { delete trix; }
38 TrixBackend::TrixBackend() : _devType(NPUCOND_TRIV2_CONN_SOCIP)
40 auto coreNum = getnumNPUdeviceByType(_devType);
46 std::vector<npudev_h> handles;
47 for (int i = 0; i < coreNum; ++i)
50 if (getNPUdeviceByType(&handle, _devType, i) < 0)
52 // Note Run for all cores.
55 handles.emplace_back(handle);
58 if (handles.size() == 0)
63 _dev = std::make_unique<TrixDevice>();
64 _dev->handles = std::move(handles);
67 TrixBackend::~TrixBackend()
69 for (const auto &ctx : _dev->ctxs)
71 npudev_h handle = _dev->handles.at(ctx->defaultCore);
72 for (const auto id : ctx->requests)
74 removeNPU_request(handle, id);
78 for (const auto &handle : _dev->handles)
80 unregisterNPUmodel_all(handle);
85 NpuStatus TrixBackend::getVersion(std::string &version)
87 // TODO Implement details
88 return NPU_STATUS_ERROR_NOT_SUPPORTED;
91 NpuStatus TrixBackend::createContext(int deviceId, int priority, NpuContext **ctx)
93 if (deviceId >= _dev->handles.size())
95 return NPU_STATUS_ERROR_INVALID_ARGUMENT;
97 auto context = std::make_unique<NpuContext>();
98 context->defaultCore = deviceId;
99 // TODO Consider priority.
100 *ctx = context.get();
101 _dev->ctxs.emplace_back(std::move(context));
102 return NPU_STATUS_SUCCESS;
105 NpuStatus TrixBackend::destroyContext(NpuContext *ctx)
109 return NPU_STATUS_ERROR_INVALID_ARGUMENT;
112 auto citer = std::find_if(_dev->ctxs.begin(), _dev->ctxs.end(),
113 [&](std::unique_ptr<NpuContext> &c) { return c.get() == ctx; });
114 if (citer == _dev->ctxs.end())
116 return NPU_STATUS_ERROR_INVALID_ARGUMENT;
119 npudev_h handle = _dev->handles.at(ctx->defaultCore);
121 for (auto rid : ctx->requests)
123 if (removeNPU_request(handle, rid) < 0)
125 return NPU_STATUS_ERROR_OPERATION_FAILED;
127 _dev->requests.erase(rid);
130 for (auto mid : ctx->models)
132 auto &minfo = _dev->models.at(mid);
133 if (--minfo->refCount == 0)
135 if (unregisterNPUmodel(handle, mid) < 0)
137 return NPU_STATUS_ERROR_OPERATION_FAILED;
139 _dev->models.erase(mid);
143 _dev->ctxs.erase(citer);
144 return NPU_STATUS_SUCCESS;
147 NpuStatus TrixBackend::createBuffer(NpuContext *ctx, GenericBuffer *buffer)
149 // TODO Implement details
150 return NPU_STATUS_ERROR_NOT_SUPPORTED;
153 NpuStatus TrixBackend::destroyBuffer(NpuContext *ctx, GenericBuffer *buffer)
155 // TODO Implement details
156 return NPU_STATUS_ERROR_NOT_SUPPORTED;
159 NpuStatus TrixBackend::registerModel(NpuContext *ctx, const std::string &modelPath,
164 return NPU_STATUS_ERROR_INVALID_ARGUMENT;
169 std::find_if(_dev->models.begin(), _dev->models.end(),
170 [&](const std::pair<const ModelID, std::unique_ptr<TrixModelInfo>> &p) {
171 return p.second->core == ctx->defaultCore && p.second->path == modelPath;
173 // Already registered model.
174 if (iter != _dev->models.end())
176 _dev->models.at(iter->first)->refCount++;
177 ctx->models.emplace_back(iter->first);
181 auto meta = getNPUmodel_metadata(modelPath.c_str(), false);
184 return NPU_STATUS_ERROR_OPERATION_FAILED;
187 generic_buffer fileInfo;
188 fileInfo.type = BUFFER_FILE;
189 fileInfo.filepath = modelPath.c_str();
190 fileInfo.size = meta->size;
192 npudev_h handle = _dev->handles.at(ctx->defaultCore);
193 if (registerNPUmodel(handle, &fileInfo, &id) < 0)
195 return NPU_STATUS_ERROR_OPERATION_FAILED;
198 _dev->models.insert(std::make_pair(id, std::unique_ptr<TrixModelInfo>(new TrixModelInfo{
199 id, modelPath, ctx->defaultCore, meta, 1})));
200 ctx->models.emplace_back(id);
204 return NPU_STATUS_SUCCESS;
207 NpuStatus TrixBackend::unregisterModel(NpuContext *ctx, ModelID modelId)
211 return NPU_STATUS_ERROR_INVALID_ARGUMENT;
214 auto miter = std::find(ctx->models.begin(), ctx->models.end(), modelId);
215 if (miter == ctx->models.end())
217 return NPU_STATUS_ERROR_INVALID_MODEL;
220 npudev_h handle = _dev->handles.at(ctx->defaultCore);
222 for (auto riter = ctx->requests.begin(); riter != ctx->requests.end();)
224 auto &rinfo = _dev->requests.at(*riter);
225 if (rinfo->modelId == modelId)
227 if (removeNPU_request(handle, rinfo->id) < 0)
229 return NPU_STATUS_ERROR_OPERATION_FAILED;
231 _dev->requests.erase(rinfo->id);
232 riter = ctx->requests.erase(riter);
240 auto &minfo = _dev->models.at(modelId);
241 if (--minfo->refCount == 0)
243 if (unregisterNPUmodel(handle, modelId) < 0)
245 return NPU_STATUS_ERROR_OPERATION_FAILED;
247 _dev->models.erase(modelId);
250 ctx->models.erase(miter);
251 return NPU_STATUS_SUCCESS;
254 NpuStatus TrixBackend::createRequest(NpuContext *ctx, ModelID modelId, RequestID *requestId)
258 return NPU_STATUS_ERROR_INVALID_ARGUMENT;
261 auto miter = std::find(ctx->models.begin(), ctx->models.end(), modelId);
262 if (miter == ctx->models.end())
264 return NPU_STATUS_ERROR_INVALID_MODEL;
268 npudev_h handle = _dev->handles.at(ctx->defaultCore);
269 if (createNPU_request(handle, modelId, &id) < 0)
271 return NPU_STATUS_ERROR_OPERATION_FAILED;
274 _dev->requests.insert(std::make_pair(id, std::unique_ptr<TrixRequestInfo>(new TrixRequestInfo{
275 static_cast<RequestID>(id), modelId})));
276 ctx->requests.emplace_back(id);
279 return NPU_STATUS_SUCCESS;
282 NpuStatus TrixBackend::destroyRequest(NpuContext *ctx, RequestID requestId)
286 return NPU_STATUS_ERROR_INVALID_ARGUMENT;
289 auto riter = std::find(ctx->requests.begin(), ctx->requests.end(), requestId);
290 if (riter == ctx->requests.end())
292 return NPU_STATUS_ERROR_INVALID_ARGUMENT;
295 npudev_h handle = _dev->handles.at(ctx->defaultCore);
296 if (removeNPU_request(handle, requestId) < 0)
298 return NPU_STATUS_ERROR_OPERATION_FAILED;
301 _dev->requests.erase(requestId);
302 ctx->requests.erase(riter);
303 return NPU_STATUS_SUCCESS;
306 NpuStatus TrixBackend::setRequestData(NpuContext *ctx, RequestID requestId, InputBuffers *inputBufs,
307 TensorDataInfos *inputInfos, OutputBuffers *outputBufs,
308 TensorDataInfos *outputInfos)
310 auto citer = std::find_if(_dev->ctxs.begin(), _dev->ctxs.end(),
311 [&](std::unique_ptr<NpuContext> &c) { return c.get() == ctx; });
312 if (citer == _dev->ctxs.end())
314 return NPU_STATUS_ERROR_INVALID_ARGUMENT;
317 auto riter = std::find(ctx->requests.begin(), ctx->requests.end(), requestId);
318 if (riter == ctx->requests.end())
320 return NPU_STATUS_ERROR_INVALID_ARGUMENT;
323 auto &req = _dev->requests.at(requestId);
324 auto miter = std::find(ctx->models.begin(), ctx->models.end(), req->modelId);
325 if (miter == ctx->models.end())
327 return NPU_STATUS_ERROR_INVALID_MODEL;
330 // TODO Exception controll of `at`
331 auto &minfo = _dev->models.at(req->modelId);
332 if (minfo->meta->input_seg_num != inputBufs->numBuffers ||
333 minfo->meta->output_seg_num != outputBufs->numBuffers)
335 return NPU_STATUS_ERROR_INVALID_DATA;
338 auto &inInfos = req->inInfos;
339 auto &outInfos = req->outInfos;
341 inInfos->num_info = inputBufs->numBuffers;
342 for (auto i = 0; i < inInfos->num_info; ++i)
344 inInfos->info[i].layout = DATA_LAYOUT_MODEL;
345 inInfos->info[i].type = minfo->meta->input_seg_quant_type[i];
348 outInfos->num_info = outputBufs->numBuffers;
349 for (auto i = 0; i < outInfos->num_info; ++i)
351 outInfos->info[i].layout = DATA_LAYOUT_MODEL;
352 outInfos->info[i].type = minfo->meta->output_seg_quant_type[i];
355 auto &inBufs = req->inBufs;
356 auto &outBufs = req->outBufs;
358 inBufs->num_buffers = inputBufs->numBuffers;
359 for (auto i = 0; i < inBufs->num_buffers; ++i)
361 if (inputBufs->buffers[i].type == NPU_BUFFER_MAPPED)
363 inBufs->bufs[i].addr = inputBufs->buffers[i].addr;
365 else if (inputBufs->buffers[i].type == NPU_BUFFER_DMABUF)
367 // TODO Implement details
368 // inBufs.bufs[i].dmabuf = inputBufs->buffers[i].dmabuf;
369 // inBufs.bufs[i].offset = inputBufs->buffers[i].offset;
375 inBufs->bufs[i].size = inputBufs->buffers[i].size;
376 inBufs->bufs[i].type = static_cast<buffer_types>(inputBufs->buffers[i].type);
379 outBufs->num_buffers = outputBufs->numBuffers;
380 for (auto i = 0; i < outBufs->num_buffers; ++i)
382 if (outputBufs->buffers[i].type == NPU_BUFFER_MAPPED)
384 outBufs->bufs[i].addr = outputBufs->buffers[i].addr;
386 else if (outputBufs->buffers[i].type == NPU_BUFFER_DMABUF)
388 // TODO Implement details
389 // outBufs.bufs[i].dmabuf = outputBufs->buffers[i].dmabuf;
390 // outBufs.bufs[i].offset = outputBufs->buffers[i].offset;
396 outBufs->bufs[i].size = outputBufs->buffers[i].size;
397 outBufs->bufs[i].type = static_cast<buffer_types>(outputBufs->buffers[i].type);
400 npudev_h handle = _dev->handles.at(ctx->defaultCore);
401 if (setNPU_requestData(handle, requestId, inBufs.get(), inInfos.get(), outBufs.get(),
404 return NPU_STATUS_ERROR_OPERATION_FAILED;
407 return NPU_STATUS_SUCCESS;
410 NpuStatus TrixBackend::submitRequest(NpuContext *ctx, RequestID requestId)
412 // TODO Implement details
413 return NPU_STATUS_ERROR_NOT_SUPPORTED;
417 } // namespace backend