xref: /aosp_15_r20/external/executorch/backends/qualcomm/runtime/QnnManager.cpp (revision 523fa7a60841cd1ecfb9cc4201f1ca8b03ed023a)
1*523fa7a6SAndroid Build Coastguard Worker /*
2*523fa7a6SAndroid Build Coastguard Worker  * Copyright (c) Qualcomm Innovation Center, Inc.
3*523fa7a6SAndroid Build Coastguard Worker  * All rights reserved.
4*523fa7a6SAndroid Build Coastguard Worker  *
5*523fa7a6SAndroid Build Coastguard Worker  * This source code is licensed under the BSD-style license found in the
6*523fa7a6SAndroid Build Coastguard Worker  * LICENSE file in the root directory of this source tree.
7*523fa7a6SAndroid Build Coastguard Worker  */
8*523fa7a6SAndroid Build Coastguard Worker 
9*523fa7a6SAndroid Build Coastguard Worker #include <executorch/backends/qualcomm/aot/ir/qcir_utils.h>
10*523fa7a6SAndroid Build Coastguard Worker #include <executorch/backends/qualcomm/qc_binary_info_generated.h>
11*523fa7a6SAndroid Build Coastguard Worker #include <executorch/backends/qualcomm/runtime/QnnManager.h>
12*523fa7a6SAndroid Build Coastguard Worker #include <executorch/backends/qualcomm/runtime/SharedBuffer.h>
13*523fa7a6SAndroid Build Coastguard Worker #include <executorch/backends/qualcomm/runtime/Utils.h>
14*523fa7a6SAndroid Build Coastguard Worker #include <executorch/backends/qualcomm/runtime/backends/QnnBackendCommon.h>
15*523fa7a6SAndroid Build Coastguard Worker #include <executorch/backends/qualcomm/runtime/backends/QnnImplementation.h>
16*523fa7a6SAndroid Build Coastguard Worker #include <executorch/extension/tensor/tensor.h>
17*523fa7a6SAndroid Build Coastguard Worker #include <algorithm>
18*523fa7a6SAndroid Build Coastguard Worker #include <cstdlib>
19*523fa7a6SAndroid Build Coastguard Worker #include <cstring>
20*523fa7a6SAndroid Build Coastguard Worker #include <fstream>
21*523fa7a6SAndroid Build Coastguard Worker #include <string>
22*523fa7a6SAndroid Build Coastguard Worker 
23*523fa7a6SAndroid Build Coastguard Worker namespace executorch {
24*523fa7a6SAndroid Build Coastguard Worker namespace backends {
25*523fa7a6SAndroid Build Coastguard Worker namespace qnn {
26*523fa7a6SAndroid Build Coastguard Worker 
27*523fa7a6SAndroid Build Coastguard Worker using executorch::runtime::Error;
28*523fa7a6SAndroid Build Coastguard Worker 
CompareExportedInput(const std::shared_ptr<TensorWrapper> & a,const std::shared_ptr<TensorWrapper> & b)29*523fa7a6SAndroid Build Coastguard Worker bool CompareExportedInput(
30*523fa7a6SAndroid Build Coastguard Worker     const std::shared_ptr<TensorWrapper>& a,
31*523fa7a6SAndroid Build Coastguard Worker     const std::shared_ptr<TensorWrapper>& b) {
32*523fa7a6SAndroid Build Coastguard Worker   // Using the order of the nodes as external_id in AOT
33*523fa7a6SAndroid Build Coastguard Worker   // to extract the right arg from *args at runtime
34*523fa7a6SAndroid Build Coastguard Worker   int numA = std::stoi(a->GetName().substr(a->GetName().find('_') + 1));
35*523fa7a6SAndroid Build Coastguard Worker   int numB = std::stoi(b->GetName().substr(b->GetName().find('_') + 1));
36*523fa7a6SAndroid Build Coastguard Worker   return numA < numB;
37*523fa7a6SAndroid Build Coastguard Worker }
38*523fa7a6SAndroid Build Coastguard Worker 
~QnnManager()39*523fa7a6SAndroid Build Coastguard Worker QnnManager::~QnnManager() {
40*523fa7a6SAndroid Build Coastguard Worker   backend_params_ptr_.reset(new BackendConfigParameters());
41*523fa7a6SAndroid Build Coastguard Worker   logger_.reset();
42*523fa7a6SAndroid Build Coastguard Worker   qnn_loaded_backend_.TerminateAllBackends();
43*523fa7a6SAndroid Build Coastguard Worker }
44*523fa7a6SAndroid Build Coastguard Worker 
QnnManager(const QnnExecuTorchOptions * options,const QnnExecuTorchContextBinary & qnn_executorch_context_binary)45*523fa7a6SAndroid Build Coastguard Worker QnnManager::QnnManager(
46*523fa7a6SAndroid Build Coastguard Worker     const QnnExecuTorchOptions* options,
47*523fa7a6SAndroid Build Coastguard Worker     const QnnExecuTorchContextBinary& qnn_executorch_context_binary)
48*523fa7a6SAndroid Build Coastguard Worker     : qnn_context_blob_(qnn_executorch_context_binary),
49*523fa7a6SAndroid Build Coastguard Worker       qnn_loaded_backend_(""),
50*523fa7a6SAndroid Build Coastguard Worker       // options' life cycle is decided by compiler specs which is
51*523fa7a6SAndroid Build Coastguard Worker       // kept by executorch runtime framework
52*523fa7a6SAndroid Build Coastguard Worker       // please pay attention to any potential seg fault
53*523fa7a6SAndroid Build Coastguard Worker       options_(options) {
54*523fa7a6SAndroid Build Coastguard Worker   QnnExecuTorchBackendType backend_type =
55*523fa7a6SAndroid Build Coastguard Worker       options->backend_options()->backend_type();
56*523fa7a6SAndroid Build Coastguard Worker   std::string library_path = options->library_path()->str();
57*523fa7a6SAndroid Build Coastguard Worker 
58*523fa7a6SAndroid Build Coastguard Worker   if (options->log_level() >= QnnExecuTorchLogLevel::kLogLevelInfo) {
59*523fa7a6SAndroid Build Coastguard Worker     QNN_EXECUTORCH_LOG_INFO(
60*523fa7a6SAndroid Build Coastguard Worker         "soc_model in soc_info: %s",
61*523fa7a6SAndroid Build Coastguard Worker         EnumNameQcomChipset(options_->soc_info()->soc_model()));
62*523fa7a6SAndroid Build Coastguard Worker     QNN_EXECUTORCH_LOG_INFO(
63*523fa7a6SAndroid Build Coastguard Worker         "backend_type: %s", EnumNameQnnExecuTorchBackendType(backend_type));
64*523fa7a6SAndroid Build Coastguard Worker     QNN_EXECUTORCH_LOG_INFO("graph_name: %s", options_->graph_name()->c_str());
65*523fa7a6SAndroid Build Coastguard Worker     QNN_EXECUTORCH_LOG_INFO("library_path: %s", library_path.c_str());
66*523fa7a6SAndroid Build Coastguard Worker     QNN_EXECUTORCH_LOG_INFO("dump intermediate outputs: %s", IsTensorDump());
67*523fa7a6SAndroid Build Coastguard Worker     QNN_EXECUTORCH_LOG_INFO(
68*523fa7a6SAndroid Build Coastguard Worker         "log_level: %s", EnumNameQnnExecuTorchLogLevel(options_->log_level()));
69*523fa7a6SAndroid Build Coastguard Worker     QNN_EXECUTORCH_LOG_INFO(
70*523fa7a6SAndroid Build Coastguard Worker         "profile_level: %s",
71*523fa7a6SAndroid Build Coastguard Worker         EnumNameQnnExecuTorchProfileLevel(options_->profile_level()));
72*523fa7a6SAndroid Build Coastguard Worker     QNN_EXECUTORCH_LOG_INFO(
73*523fa7a6SAndroid Build Coastguard Worker         "the size of qnn context binary: %d",
74*523fa7a6SAndroid Build Coastguard Worker         qnn_executorch_context_binary.nbytes);
75*523fa7a6SAndroid Build Coastguard Worker     QNN_EXECUTORCH_LOG_INFO(
76*523fa7a6SAndroid Build Coastguard Worker         "Is on-device graph construction: %d", options->online_prepare());
77*523fa7a6SAndroid Build Coastguard Worker     QNN_EXECUTORCH_LOG_INFO(
78*523fa7a6SAndroid Build Coastguard Worker         "Enable shared buffer: %d", options->shared_buffer());
79*523fa7a6SAndroid Build Coastguard Worker   }
80*523fa7a6SAndroid Build Coastguard Worker 
81*523fa7a6SAndroid Build Coastguard Worker   if (library_path.empty()) {
82*523fa7a6SAndroid Build Coastguard Worker     switch (backend_type) {
83*523fa7a6SAndroid Build Coastguard Worker       case QnnExecuTorchBackendType::kHtpBackend:
84*523fa7a6SAndroid Build Coastguard Worker         library_path = htp_library_name_;
85*523fa7a6SAndroid Build Coastguard Worker         break;
86*523fa7a6SAndroid Build Coastguard Worker       case QnnExecuTorchBackendType::kDspBackend:
87*523fa7a6SAndroid Build Coastguard Worker         library_path = dsp_library_name_;
88*523fa7a6SAndroid Build Coastguard Worker         break;
89*523fa7a6SAndroid Build Coastguard Worker       case QnnExecuTorchBackendType::kGpuBackend:
90*523fa7a6SAndroid Build Coastguard Worker         library_path = gpu_library_name_;
91*523fa7a6SAndroid Build Coastguard Worker         break;
92*523fa7a6SAndroid Build Coastguard Worker       default:
93*523fa7a6SAndroid Build Coastguard Worker         QNN_EXECUTORCH_LOG_ERROR("Unknown backend type: %d", backend_type);
94*523fa7a6SAndroid Build Coastguard Worker         break;
95*523fa7a6SAndroid Build Coastguard Worker     }
96*523fa7a6SAndroid Build Coastguard Worker   }
97*523fa7a6SAndroid Build Coastguard Worker   qnn_loaded_backend_ = QnnImplementation(library_path);
98*523fa7a6SAndroid Build Coastguard Worker   backend_params_ptr_ = std::make_unique<BackendConfigParameters>();
99*523fa7a6SAndroid Build Coastguard Worker }
100*523fa7a6SAndroid Build Coastguard Worker 
LoadQnnLibrary()101*523fa7a6SAndroid Build Coastguard Worker Error QnnManager::LoadQnnLibrary() {
102*523fa7a6SAndroid Build Coastguard Worker   Error ret = qnn_loaded_backend_.Load(nullptr);
103*523fa7a6SAndroid Build Coastguard Worker   return ret;
104*523fa7a6SAndroid Build Coastguard Worker }
105*523fa7a6SAndroid Build Coastguard Worker 
PreRegisterMem()106*523fa7a6SAndroid Build Coastguard Worker Error QnnManager::PreRegisterMem() {
107*523fa7a6SAndroid Build Coastguard Worker   SharedBuffer& shared_buffer_manager = SharedBuffer::GetSharedBufferManager();
108*523fa7a6SAndroid Build Coastguard Worker   for (const auto info : shared_buffer_manager.GetCustomMemTensorInfoSet()) {
109*523fa7a6SAndroid Build Coastguard Worker     void* unaligned_custom_mem_base =
110*523fa7a6SAndroid Build Coastguard Worker         shared_buffer_manager.GetUnAlignedAddr(info.custom_mem);
111*523fa7a6SAndroid Build Coastguard Worker 
112*523fa7a6SAndroid Build Coastguard Worker     size_t tensor_offset = (static_cast<char*>(info.custom_mem) -
113*523fa7a6SAndroid Build Coastguard Worker                             static_cast<char*>(unaligned_custom_mem_base)) +
114*523fa7a6SAndroid Build Coastguard Worker         info.pos;
115*523fa7a6SAndroid Build Coastguard Worker     size_t total_custom_mem_size =
116*523fa7a6SAndroid Build Coastguard Worker         shared_buffer_manager.GetAllocatedSize(info.custom_mem);
117*523fa7a6SAndroid Build Coastguard Worker 
118*523fa7a6SAndroid Build Coastguard Worker     int32_t mem_fd = shared_buffer_manager.MemToFd(unaligned_custom_mem_base);
119*523fa7a6SAndroid Build Coastguard Worker     if (mem_fd == -1) {
120*523fa7a6SAndroid Build Coastguard Worker       QNN_EXECUTORCH_LOG_WARN(
121*523fa7a6SAndroid Build Coastguard Worker           "PreRegisterMem failed to get file descriptor.",
122*523fa7a6SAndroid Build Coastguard Worker           "custom_mem: %p",
123*523fa7a6SAndroid Build Coastguard Worker           "tensor_addr: %p",
124*523fa7a6SAndroid Build Coastguard Worker           "pos: %uz",
125*523fa7a6SAndroid Build Coastguard Worker           "tensor_bytes: %uz",
126*523fa7a6SAndroid Build Coastguard Worker           "shape: %p",
127*523fa7a6SAndroid Build Coastguard Worker           "rank: %zu",
128*523fa7a6SAndroid Build Coastguard Worker           "qnn_dtype: %X",
129*523fa7a6SAndroid Build Coastguard Worker           info.custom_mem,
130*523fa7a6SAndroid Build Coastguard Worker           info.tensor_addr,
131*523fa7a6SAndroid Build Coastguard Worker           info.pos,
132*523fa7a6SAndroid Build Coastguard Worker           info.tensor_bytes,
133*523fa7a6SAndroid Build Coastguard Worker           info.shape,
134*523fa7a6SAndroid Build Coastguard Worker           info.rank,
135*523fa7a6SAndroid Build Coastguard Worker           info.dtype);
136*523fa7a6SAndroid Build Coastguard Worker       return Error::Internal;
137*523fa7a6SAndroid Build Coastguard Worker     }
138*523fa7a6SAndroid Build Coastguard Worker 
139*523fa7a6SAndroid Build Coastguard Worker     ET_CHECK_OR_RETURN_ERROR(
140*523fa7a6SAndroid Build Coastguard Worker         backend_params_ptr_->qnn_mem_manager_ptr_->PreRegisterCustomMemHandle(
141*523fa7a6SAndroid Build Coastguard Worker             mem_fd,
142*523fa7a6SAndroid Build Coastguard Worker             unaligned_custom_mem_base,
143*523fa7a6SAndroid Build Coastguard Worker             total_custom_mem_size,
144*523fa7a6SAndroid Build Coastguard Worker             tensor_offset,
145*523fa7a6SAndroid Build Coastguard Worker             info) == Error::Ok,
146*523fa7a6SAndroid Build Coastguard Worker         Internal,
147*523fa7a6SAndroid Build Coastguard Worker         "Fail to register to shared memory.");
148*523fa7a6SAndroid Build Coastguard Worker   }
149*523fa7a6SAndroid Build Coastguard Worker   return Error::Ok;
150*523fa7a6SAndroid Build Coastguard Worker }
151*523fa7a6SAndroid Build Coastguard Worker 
RegisterMem(void * data_ptr,const std::shared_ptr<TensorWrapper> & tensor_wrapper)152*523fa7a6SAndroid Build Coastguard Worker Error QnnManager::RegisterMem(
153*523fa7a6SAndroid Build Coastguard Worker     void* data_ptr,
154*523fa7a6SAndroid Build Coastguard Worker     const std::shared_ptr<TensorWrapper>& tensor_wrapper) {
155*523fa7a6SAndroid Build Coastguard Worker   SharedBuffer& shared_buffer_manager = SharedBuffer::GetSharedBufferManager();
156*523fa7a6SAndroid Build Coastguard Worker   // Not enable shared buffer
157*523fa7a6SAndroid Build Coastguard Worker   if (!options_->shared_buffer())
158*523fa7a6SAndroid Build Coastguard Worker     return Error::Internal;
159*523fa7a6SAndroid Build Coastguard Worker 
160*523fa7a6SAndroid Build Coastguard Worker   if (backend_params_ptr_->qnn_mem_manager_ptr_ == nullptr) {
161*523fa7a6SAndroid Build Coastguard Worker     QNN_EXECUTORCH_LOG_WARN(
162*523fa7a6SAndroid Build Coastguard Worker         "Backend %s doesn't supported shared buffer.",
163*523fa7a6SAndroid Build Coastguard Worker         EnumNameQnnExecuTorchBackendType(
164*523fa7a6SAndroid Build Coastguard Worker             options_->backend_options()->backend_type()));
165*523fa7a6SAndroid Build Coastguard Worker     return Error::Internal;
166*523fa7a6SAndroid Build Coastguard Worker   }
167*523fa7a6SAndroid Build Coastguard Worker 
168*523fa7a6SAndroid Build Coastguard Worker   void* custom_mem_base = shared_buffer_manager.GetCustomMemBase(data_ptr);
169*523fa7a6SAndroid Build Coastguard Worker   if (custom_mem_base != nullptr) {
170*523fa7a6SAndroid Build Coastguard Worker     return RegisterCustomMem(data_ptr, custom_mem_base, tensor_wrapper);
171*523fa7a6SAndroid Build Coastguard Worker   }
172*523fa7a6SAndroid Build Coastguard Worker   return RegisterIonMem(data_ptr, tensor_wrapper);
173*523fa7a6SAndroid Build Coastguard Worker }
174*523fa7a6SAndroid Build Coastguard Worker 
RegisterIonMem(void * data_ptr,const std::shared_ptr<TensorWrapper> & tensor_wrapper)175*523fa7a6SAndroid Build Coastguard Worker Error QnnManager::RegisterIonMem(
176*523fa7a6SAndroid Build Coastguard Worker     void* data_ptr,
177*523fa7a6SAndroid Build Coastguard Worker     const std::shared_ptr<TensorWrapper>& tensor_wrapper) {
178*523fa7a6SAndroid Build Coastguard Worker   SharedBuffer& shared_buffer_manager = SharedBuffer::GetSharedBufferManager();
179*523fa7a6SAndroid Build Coastguard Worker   if (!shared_buffer_manager.IsAllocated(data_ptr)) {
180*523fa7a6SAndroid Build Coastguard Worker     // It means two scenarios here:
181*523fa7a6SAndroid Build Coastguard Worker     // 1. the input and output partitioned graph
182*523fa7a6SAndroid Build Coastguard Worker     // 2. Actually, user doesn't allocate shared buffer with
183*523fa7a6SAndroid Build Coastguard Worker     // QnnExecuTorchAllocCustomMem API
184*523fa7a6SAndroid Build Coastguard Worker     return Error::Internal;
185*523fa7a6SAndroid Build Coastguard Worker   } else if (backend_params_ptr_->qnn_mem_manager_ptr_->IsRegistered(
186*523fa7a6SAndroid Build Coastguard Worker                  tensor_wrapper->GetMemHandle(), data_ptr)) {
187*523fa7a6SAndroid Build Coastguard Worker     if (options_->log_level() >= QnnExecuTorchLogLevel::kLogLevelInfo)
188*523fa7a6SAndroid Build Coastguard Worker       QNN_EXECUTORCH_LOG_INFO(
189*523fa7a6SAndroid Build Coastguard Worker           "Tensor name %s has been registered shared memory.",
190*523fa7a6SAndroid Build Coastguard Worker           tensor_wrapper->GetName().c_str());
191*523fa7a6SAndroid Build Coastguard Worker     return Error::Ok;
192*523fa7a6SAndroid Build Coastguard Worker   }
193*523fa7a6SAndroid Build Coastguard Worker 
194*523fa7a6SAndroid Build Coastguard Worker   int32_t mem_fd = shared_buffer_manager.MemToFd(data_ptr);
195*523fa7a6SAndroid Build Coastguard Worker   if (mem_fd == -1) {
196*523fa7a6SAndroid Build Coastguard Worker     QNN_EXECUTORCH_LOG_WARN(
197*523fa7a6SAndroid Build Coastguard Worker         "Tensor name %s is failed to get file descriptor.",
198*523fa7a6SAndroid Build Coastguard Worker         tensor_wrapper->GetName().c_str());
199*523fa7a6SAndroid Build Coastguard Worker     return Error::Internal;
200*523fa7a6SAndroid Build Coastguard Worker   }
201*523fa7a6SAndroid Build Coastguard Worker   ET_CHECK_OR_RETURN_ERROR(
202*523fa7a6SAndroid Build Coastguard Worker       backend_params_ptr_->qnn_mem_manager_ptr_->RegisterIonMem(
203*523fa7a6SAndroid Build Coastguard Worker           tensor_wrapper, mem_fd, data_ptr) == Error::Ok,
204*523fa7a6SAndroid Build Coastguard Worker       Internal,
205*523fa7a6SAndroid Build Coastguard Worker       "Fail to register to shared memory.");
206*523fa7a6SAndroid Build Coastguard Worker 
207*523fa7a6SAndroid Build Coastguard Worker   return Error::Ok;
208*523fa7a6SAndroid Build Coastguard Worker }
209*523fa7a6SAndroid Build Coastguard Worker 
RegisterCustomMem(void * data_ptr,void * custom_mem_base,const std::shared_ptr<TensorWrapper> & tensor_wrapper)210*523fa7a6SAndroid Build Coastguard Worker Error QnnManager::RegisterCustomMem(
211*523fa7a6SAndroid Build Coastguard Worker     void* data_ptr,
212*523fa7a6SAndroid Build Coastguard Worker     void* custom_mem_base,
213*523fa7a6SAndroid Build Coastguard Worker     const std::shared_ptr<TensorWrapper>& tensor_wrapper) {
214*523fa7a6SAndroid Build Coastguard Worker   if (backend_params_ptr_->qnn_mem_manager_ptr_->IsRegistered(
215*523fa7a6SAndroid Build Coastguard Worker           tensor_wrapper->GetMemHandle(), data_ptr)) {
216*523fa7a6SAndroid Build Coastguard Worker     if (options_->log_level() >= QnnExecuTorchLogLevel::kLogLevelInfo)
217*523fa7a6SAndroid Build Coastguard Worker       QNN_EXECUTORCH_LOG_INFO(
218*523fa7a6SAndroid Build Coastguard Worker           "Tensor name %s has been registered shared memory.",
219*523fa7a6SAndroid Build Coastguard Worker           tensor_wrapper->GetName().c_str());
220*523fa7a6SAndroid Build Coastguard Worker     return Error::Ok;
221*523fa7a6SAndroid Build Coastguard Worker   }
222*523fa7a6SAndroid Build Coastguard Worker 
223*523fa7a6SAndroid Build Coastguard Worker   CustomMemTensorInfo info{
224*523fa7a6SAndroid Build Coastguard Worker       custom_mem_base,
225*523fa7a6SAndroid Build Coastguard Worker       data_ptr,
226*523fa7a6SAndroid Build Coastguard Worker       static_cast<size_t>(
227*523fa7a6SAndroid Build Coastguard Worker           static_cast<char*>(data_ptr) - static_cast<char*>(custom_mem_base)),
228*523fa7a6SAndroid Build Coastguard Worker       tensor_wrapper->GetBytes(),
229*523fa7a6SAndroid Build Coastguard Worker       tensor_wrapper->GetDims(),
230*523fa7a6SAndroid Build Coastguard Worker       tensor_wrapper->GetRank(),
231*523fa7a6SAndroid Build Coastguard Worker       qnn_dtype_to_scalar_type_[tensor_wrapper->GetDataType()]};
232*523fa7a6SAndroid Build Coastguard Worker 
233*523fa7a6SAndroid Build Coastguard Worker   Qnn_MemHandle_t pre_registered_handle =
234*523fa7a6SAndroid Build Coastguard Worker       backend_params_ptr_->qnn_mem_manager_ptr_->GetPreRegisteredHandle(info);
235*523fa7a6SAndroid Build Coastguard Worker   if (pre_registered_handle != nullptr) {
236*523fa7a6SAndroid Build Coastguard Worker     if (options_->log_level() >= QnnExecuTorchLogLevel::kLogLevelInfo) {
237*523fa7a6SAndroid Build Coastguard Worker       QNN_EXECUTORCH_LOG_INFO(
238*523fa7a6SAndroid Build Coastguard Worker           "Tensor name %s found a pre-registered memHandle.",
239*523fa7a6SAndroid Build Coastguard Worker           tensor_wrapper->GetName().c_str());
240*523fa7a6SAndroid Build Coastguard Worker     }
241*523fa7a6SAndroid Build Coastguard Worker     return backend_params_ptr_->qnn_mem_manager_ptr_->SetMemHandle(
242*523fa7a6SAndroid Build Coastguard Worker         tensor_wrapper, data_ptr, pre_registered_handle);
243*523fa7a6SAndroid Build Coastguard Worker   }
244*523fa7a6SAndroid Build Coastguard Worker 
245*523fa7a6SAndroid Build Coastguard Worker   SharedBuffer& shared_buffer_manager = SharedBuffer::GetSharedBufferManager();
246*523fa7a6SAndroid Build Coastguard Worker   void* unaligned_custom_mem_base =
247*523fa7a6SAndroid Build Coastguard Worker       shared_buffer_manager.GetUnAlignedAddr(custom_mem_base);
248*523fa7a6SAndroid Build Coastguard Worker 
249*523fa7a6SAndroid Build Coastguard Worker   size_t tensor_offset = static_cast<char*>(custom_mem_base) -
250*523fa7a6SAndroid Build Coastguard Worker       static_cast<char*>(unaligned_custom_mem_base) + info.pos;
251*523fa7a6SAndroid Build Coastguard Worker   size_t total_custom_mem_size =
252*523fa7a6SAndroid Build Coastguard Worker       shared_buffer_manager.GetAllocatedSize(custom_mem_base);
253*523fa7a6SAndroid Build Coastguard Worker 
254*523fa7a6SAndroid Build Coastguard Worker   int32_t mem_fd = shared_buffer_manager.MemToFd(unaligned_custom_mem_base);
255*523fa7a6SAndroid Build Coastguard Worker   if (mem_fd == -1) {
256*523fa7a6SAndroid Build Coastguard Worker     QNN_EXECUTORCH_LOG_WARN(
257*523fa7a6SAndroid Build Coastguard Worker         "Tensor name %s failed to get file descriptor.",
258*523fa7a6SAndroid Build Coastguard Worker         tensor_wrapper->GetName().c_str());
259*523fa7a6SAndroid Build Coastguard Worker     return Error::Internal;
260*523fa7a6SAndroid Build Coastguard Worker   }
261*523fa7a6SAndroid Build Coastguard Worker 
262*523fa7a6SAndroid Build Coastguard Worker   ET_CHECK_OR_RETURN_ERROR(
263*523fa7a6SAndroid Build Coastguard Worker       backend_params_ptr_->qnn_mem_manager_ptr_->RegisterCustomMem(
264*523fa7a6SAndroid Build Coastguard Worker           tensor_wrapper,
265*523fa7a6SAndroid Build Coastguard Worker           mem_fd,
266*523fa7a6SAndroid Build Coastguard Worker           data_ptr,
267*523fa7a6SAndroid Build Coastguard Worker           unaligned_custom_mem_base,
268*523fa7a6SAndroid Build Coastguard Worker           total_custom_mem_size,
269*523fa7a6SAndroid Build Coastguard Worker           tensor_offset) == Error::Ok,
270*523fa7a6SAndroid Build Coastguard Worker       Internal,
271*523fa7a6SAndroid Build Coastguard Worker       "Fail to register to shared memory.");
272*523fa7a6SAndroid Build Coastguard Worker 
273*523fa7a6SAndroid Build Coastguard Worker   return Error::Ok;
274*523fa7a6SAndroid Build Coastguard Worker }
275*523fa7a6SAndroid Build Coastguard Worker 
Init()276*523fa7a6SAndroid Build Coastguard Worker Error QnnManager::Init() {
277*523fa7a6SAndroid Build Coastguard Worker   ET_CHECK_OR_RETURN_ERROR(
278*523fa7a6SAndroid Build Coastguard Worker       LoadQnnLibrary() == Error::Ok, Internal, "Fail to load Qnn library");
279*523fa7a6SAndroid Build Coastguard Worker   logger_ = std::make_unique<QnnLogger>(
280*523fa7a6SAndroid Build Coastguard Worker       qnn_loaded_backend_, LoggingCallback, options_->log_level());
281*523fa7a6SAndroid Build Coastguard Worker   if (backend_params_ptr_->backend_init_state_ ==
282*523fa7a6SAndroid Build Coastguard Worker       BackendInitializeState::UNINITIALIZED) {
283*523fa7a6SAndroid Build Coastguard Worker     QNN_EXECUTORCH_LOG_INFO(
284*523fa7a6SAndroid Build Coastguard Worker         "Initialize Qnn backend "
285*523fa7a6SAndroid Build Coastguard Worker         "parameters for Qnn executorch backend type %d",
286*523fa7a6SAndroid Build Coastguard Worker         options_->backend_options()->backend_type());
287*523fa7a6SAndroid Build Coastguard Worker     backend_params_ptr_ = QnnBackendFactory().Create(
288*523fa7a6SAndroid Build Coastguard Worker         qnn_loaded_backend_, logger_.get(), qnn_context_blob_, options_);
289*523fa7a6SAndroid Build Coastguard Worker     ET_CHECK_OR_RETURN_ERROR(
290*523fa7a6SAndroid Build Coastguard Worker         backend_params_ptr_ != nullptr, Internal, "Failed to load Qnn backend.")
291*523fa7a6SAndroid Build Coastguard Worker     ET_CHECK_OR_RETURN_ERROR(
292*523fa7a6SAndroid Build Coastguard Worker         backend_params_ptr_->qnn_backend_cache_ptr_->Configure() == Error::Ok,
293*523fa7a6SAndroid Build Coastguard Worker         Internal,
294*523fa7a6SAndroid Build Coastguard Worker         "Fail to configure Qnn backend cache");
295*523fa7a6SAndroid Build Coastguard Worker     ET_CHECK_OR_RETURN_ERROR(
296*523fa7a6SAndroid Build Coastguard Worker         backend_params_ptr_->qnn_backend_ptr_->Configure() == Error::Ok,
297*523fa7a6SAndroid Build Coastguard Worker         Internal,
298*523fa7a6SAndroid Build Coastguard Worker         "Fail to configure Qnn backend");
299*523fa7a6SAndroid Build Coastguard Worker     ET_CHECK_OR_RETURN_ERROR(
300*523fa7a6SAndroid Build Coastguard Worker         backend_params_ptr_->qnn_device_ptr_->Configure() == Error::Ok,
301*523fa7a6SAndroid Build Coastguard Worker         Internal,
302*523fa7a6SAndroid Build Coastguard Worker         "Fail to configure Qnn device");
303*523fa7a6SAndroid Build Coastguard Worker     ET_CHECK_OR_RETURN_ERROR(
304*523fa7a6SAndroid Build Coastguard Worker         backend_params_ptr_->qnn_context_ptr_->Configure() == Error::Ok,
305*523fa7a6SAndroid Build Coastguard Worker         Internal,
306*523fa7a6SAndroid Build Coastguard Worker         "Fail to configure Qnn context");
307*523fa7a6SAndroid Build Coastguard Worker     for (const std::string& graph_name :
308*523fa7a6SAndroid Build Coastguard Worker          backend_params_ptr_->qnn_context_ptr_->GetGraphNames()) {
309*523fa7a6SAndroid Build Coastguard Worker       ET_CHECK_OR_RETURN_ERROR(
310*523fa7a6SAndroid Build Coastguard Worker           backend_params_ptr_->qnn_graph_ptr_->Configure(graph_name) ==
311*523fa7a6SAndroid Build Coastguard Worker               Error::Ok,
312*523fa7a6SAndroid Build Coastguard Worker           Internal,
313*523fa7a6SAndroid Build Coastguard Worker           "Fail to configure Qnn graph");
314*523fa7a6SAndroid Build Coastguard Worker     }
315*523fa7a6SAndroid Build Coastguard Worker     backend_params_ptr_->backend_init_state_ =
316*523fa7a6SAndroid Build Coastguard Worker         BackendInitializeState::INITIALIZED;
317*523fa7a6SAndroid Build Coastguard Worker   }
318*523fa7a6SAndroid Build Coastguard Worker 
319*523fa7a6SAndroid Build Coastguard Worker #if defined(__aarch64__)
320*523fa7a6SAndroid Build Coastguard Worker   ET_CHECK_OR_RETURN_ERROR(
321*523fa7a6SAndroid Build Coastguard Worker       PreRegisterMem() == Error::Ok,
322*523fa7a6SAndroid Build Coastguard Worker       Internal,
323*523fa7a6SAndroid Build Coastguard Worker       "Fail to pre register custom memory handle");
324*523fa7a6SAndroid Build Coastguard Worker #endif
325*523fa7a6SAndroid Build Coastguard Worker   return Error::Ok;
326*523fa7a6SAndroid Build Coastguard Worker }
327*523fa7a6SAndroid Build Coastguard Worker 
AllocateTensor(const std::string & graph_name)328*523fa7a6SAndroid Build Coastguard Worker Error QnnManager::AllocateTensor(const std::string& graph_name) {
329*523fa7a6SAndroid Build Coastguard Worker   std::vector<Qnn_Tensor_t> input_tensors =
330*523fa7a6SAndroid Build Coastguard Worker       backend_params_ptr_->qnn_context_ptr_->GetGraphInputs(graph_name);
331*523fa7a6SAndroid Build Coastguard Worker   std::vector<Qnn_Tensor_t> output_tensors =
332*523fa7a6SAndroid Build Coastguard Worker       backend_params_ptr_->qnn_context_ptr_->GetGraphOutputs(graph_name);
333*523fa7a6SAndroid Build Coastguard Worker 
334*523fa7a6SAndroid Build Coastguard Worker   for (auto& tensor : input_tensors) {
335*523fa7a6SAndroid Build Coastguard Worker     std::shared_ptr<TensorWrapper> tensor_wrapper = CreateTensorWrapper(tensor);
336*523fa7a6SAndroid Build Coastguard Worker     tensor_wrapper->UpdateQnnTensorMeta(tensor);
337*523fa7a6SAndroid Build Coastguard Worker     input_tensors_[graph_name].emplace_back(std::move(tensor_wrapper));
338*523fa7a6SAndroid Build Coastguard Worker   }
339*523fa7a6SAndroid Build Coastguard Worker   if (!options_->is_from_context_binary()) {
340*523fa7a6SAndroid Build Coastguard Worker     std::sort(
341*523fa7a6SAndroid Build Coastguard Worker         input_tensors_[graph_name].begin(),
342*523fa7a6SAndroid Build Coastguard Worker         input_tensors_[graph_name].end(),
343*523fa7a6SAndroid Build Coastguard Worker         CompareExportedInput);
344*523fa7a6SAndroid Build Coastguard Worker   }
345*523fa7a6SAndroid Build Coastguard Worker   for (size_t i = 0; i < output_tensors.size(); ++i) {
346*523fa7a6SAndroid Build Coastguard Worker     std::shared_ptr<TensorWrapper> tensor_wrapper =
347*523fa7a6SAndroid Build Coastguard Worker         CreateTensorWrapper(output_tensors[i]);
348*523fa7a6SAndroid Build Coastguard Worker     tensor_wrapper->UpdateQnnTensorMeta(output_tensors[i]);
349*523fa7a6SAndroid Build Coastguard Worker     const std::string& tensor_name = tensor_wrapper->GetName();
350*523fa7a6SAndroid Build Coastguard Worker     // this is required by identifying shared buffer mechanism
351*523fa7a6SAndroid Build Coastguard Worker     // info might be missed if context binary came from qnn_converter
352*523fa7a6SAndroid Build Coastguard Worker     if (options_->is_from_context_binary() &&
353*523fa7a6SAndroid Build Coastguard Worker         tensor_name.find("output_") == std::string::npos) {
354*523fa7a6SAndroid Build Coastguard Worker       tensor_wrapper->SetName("output_" + tensor_name);
355*523fa7a6SAndroid Build Coastguard Worker     }
356*523fa7a6SAndroid Build Coastguard Worker     if (IsTensorDump()) {
357*523fa7a6SAndroid Build Coastguard Worker       tensor_wrapper->AllocateDataBuffer();
358*523fa7a6SAndroid Build Coastguard Worker     }
359*523fa7a6SAndroid Build Coastguard Worker     output_tensors_[graph_name].emplace_back(std::move(tensor_wrapper));
360*523fa7a6SAndroid Build Coastguard Worker   }
361*523fa7a6SAndroid Build Coastguard Worker   return Error::Ok;
362*523fa7a6SAndroid Build Coastguard Worker }
363*523fa7a6SAndroid Build Coastguard Worker 
AllocateTensor(const std::string & graph_name,std::vector<std::shared_ptr<TensorWrapper>> & inputs,std::vector<std::shared_ptr<TensorWrapper>> & outputs)364*523fa7a6SAndroid Build Coastguard Worker Error QnnManager::AllocateTensor(
365*523fa7a6SAndroid Build Coastguard Worker     const std::string& graph_name,
366*523fa7a6SAndroid Build Coastguard Worker     std::vector<std::shared_ptr<TensorWrapper>>& inputs,
367*523fa7a6SAndroid Build Coastguard Worker     std::vector<std::shared_ptr<TensorWrapper>>& outputs) {
368*523fa7a6SAndroid Build Coastguard Worker   input_tensors_[graph_name] = std::move(inputs);
369*523fa7a6SAndroid Build Coastguard Worker   // TODO: suuport per-tensor dump in online prepare mode
370*523fa7a6SAndroid Build Coastguard Worker   //       should be achievable with some pre-process
371*523fa7a6SAndroid Build Coastguard Worker   if (!options_->is_from_context_binary()) {
372*523fa7a6SAndroid Build Coastguard Worker     std::sort(
373*523fa7a6SAndroid Build Coastguard Worker         input_tensors_[graph_name].begin(),
374*523fa7a6SAndroid Build Coastguard Worker         input_tensors_[graph_name].end(),
375*523fa7a6SAndroid Build Coastguard Worker         CompareExportedInput);
376*523fa7a6SAndroid Build Coastguard Worker   }
377*523fa7a6SAndroid Build Coastguard Worker   output_tensors_[graph_name] = std::move(outputs);
378*523fa7a6SAndroid Build Coastguard Worker   return Error::Ok;
379*523fa7a6SAndroid Build Coastguard Worker }
380*523fa7a6SAndroid Build Coastguard Worker 
Execute(const std::string & graph_name,const std::vector<Qnn_Tensor_t> & input_tensor_structs,std::vector<Qnn_Tensor_t> & output_tensor_structs,executorch::runtime::EventTracer * event_tracer)381*523fa7a6SAndroid Build Coastguard Worker Error QnnManager::Execute(
382*523fa7a6SAndroid Build Coastguard Worker     const std::string& graph_name,
383*523fa7a6SAndroid Build Coastguard Worker     const std::vector<Qnn_Tensor_t>& input_tensor_structs,
384*523fa7a6SAndroid Build Coastguard Worker     std::vector<Qnn_Tensor_t>& output_tensor_structs,
385*523fa7a6SAndroid Build Coastguard Worker     executorch::runtime::EventTracer* event_tracer) {
386*523fa7a6SAndroid Build Coastguard Worker   Qnn_ErrorHandle_t error = QNN_SUCCESS;
387*523fa7a6SAndroid Build Coastguard Worker 
388*523fa7a6SAndroid Build Coastguard Worker   error = backend_params_ptr_->qnn_graph_ptr_->GraphExecute(
389*523fa7a6SAndroid Build Coastguard Worker       graph_name, input_tensor_structs, output_tensor_structs);
390*523fa7a6SAndroid Build Coastguard Worker 
391*523fa7a6SAndroid Build Coastguard Worker   if (error != QNN_SUCCESS) {
392*523fa7a6SAndroid Build Coastguard Worker     QNN_EXECUTORCH_LOG_ERROR(
393*523fa7a6SAndroid Build Coastguard Worker         "qnn_graph_execute failed. Error %d", QNN_GET_ERROR_CODE(error));
394*523fa7a6SAndroid Build Coastguard Worker     return Error::Internal;
395*523fa7a6SAndroid Build Coastguard Worker   }
396*523fa7a6SAndroid Build Coastguard Worker   if (IsTensorDump()) {
397*523fa7a6SAndroid Build Coastguard Worker     // TODO: Need to handle the graph which is partitioned.
398*523fa7a6SAndroid Build Coastguard Worker     // Maybe we could use graph name.
399*523fa7a6SAndroid Build Coastguard Worker     for (std::size_t out_idx = 0; out_idx < output_tensor_structs.size();
400*523fa7a6SAndroid Build Coastguard Worker          ++out_idx) {
401*523fa7a6SAndroid Build Coastguard Worker       const Qnn_Tensor_t& output_tensor = output_tensor_structs[out_idx];
402*523fa7a6SAndroid Build Coastguard Worker       std::vector<executorch::aten::SizesType> sizes(
403*523fa7a6SAndroid Build Coastguard Worker           QNN_VER_PTR(output_tensor)->dimensions,
404*523fa7a6SAndroid Build Coastguard Worker           QNN_VER_PTR(output_tensor)->dimensions +
405*523fa7a6SAndroid Build Coastguard Worker               QNN_VER_PTR(output_tensor)->rank);
406*523fa7a6SAndroid Build Coastguard Worker 
407*523fa7a6SAndroid Build Coastguard Worker       auto dump_tensor = executorch::extension::from_blob(
408*523fa7a6SAndroid Build Coastguard Worker           QNN_VER_PTR(output_tensor)->clientBuf.data,
409*523fa7a6SAndroid Build Coastguard Worker           sizes,
410*523fa7a6SAndroid Build Coastguard Worker           qnn_dtype_to_scalar_type_[QNN_VER_PTR(output_tensor)->dataType]);
411*523fa7a6SAndroid Build Coastguard Worker 
412*523fa7a6SAndroid Build Coastguard Worker       executorch::runtime::event_tracer_log_output_delegate<
413*523fa7a6SAndroid Build Coastguard Worker           executorch::aten::Tensor>(
414*523fa7a6SAndroid Build Coastguard Worker           event_tracer,
415*523fa7a6SAndroid Build Coastguard Worker           QNN_VER_PTR(output_tensor)->name,
416*523fa7a6SAndroid Build Coastguard Worker           /*delegate_debug_id=*/
417*523fa7a6SAndroid Build Coastguard Worker           static_cast<executorch::runtime::DebugHandle>(-1),
418*523fa7a6SAndroid Build Coastguard Worker           *dump_tensor);
419*523fa7a6SAndroid Build Coastguard Worker     }
420*523fa7a6SAndroid Build Coastguard Worker   }
421*523fa7a6SAndroid Build Coastguard Worker 
422*523fa7a6SAndroid Build Coastguard Worker   return Error::Ok;
423*523fa7a6SAndroid Build Coastguard Worker }
424*523fa7a6SAndroid Build Coastguard Worker 
ProfileExecuteData(const std::string & graph_name,executorch::runtime::EventTracer * event_tracer)425*523fa7a6SAndroid Build Coastguard Worker Error QnnManager::ProfileExecuteData(
426*523fa7a6SAndroid Build Coastguard Worker     const std::string& graph_name,
427*523fa7a6SAndroid Build Coastguard Worker     executorch::runtime::EventTracer* event_tracer) {
428*523fa7a6SAndroid Build Coastguard Worker   Qnn_ErrorHandle_t error = QNN_SUCCESS;
429*523fa7a6SAndroid Build Coastguard Worker   if (options_->profile_level() != QnnExecuTorchProfileLevel::kProfileOff) {
430*523fa7a6SAndroid Build Coastguard Worker     error = backend_params_ptr_->qnn_graph_ptr_->ProfileExecuteData(
431*523fa7a6SAndroid Build Coastguard Worker         graph_name, event_tracer);
432*523fa7a6SAndroid Build Coastguard Worker     if (error != QNN_SUCCESS) {
433*523fa7a6SAndroid Build Coastguard Worker       QNN_EXECUTORCH_LOG_ERROR(
434*523fa7a6SAndroid Build Coastguard Worker           " Failed to profile. Error %d", QNN_GET_ERROR_CODE(error));
435*523fa7a6SAndroid Build Coastguard Worker       return Error::Internal;
436*523fa7a6SAndroid Build Coastguard Worker     }
437*523fa7a6SAndroid Build Coastguard Worker   }
438*523fa7a6SAndroid Build Coastguard Worker   return Error::Ok;
439*523fa7a6SAndroid Build Coastguard Worker }
440*523fa7a6SAndroid Build Coastguard Worker 
Destroy()441*523fa7a6SAndroid Build Coastguard Worker void QnnManager::Destroy() {
442*523fa7a6SAndroid Build Coastguard Worker   QNN_EXECUTORCH_LOG_INFO("Destroy Qnn backend parameters");
443*523fa7a6SAndroid Build Coastguard Worker   backend_params_ptr_.reset(new BackendConfigParameters());
444*523fa7a6SAndroid Build Coastguard Worker   logger_.reset();
445*523fa7a6SAndroid Build Coastguard Worker 
446*523fa7a6SAndroid Build Coastguard Worker   qnn_loaded_backend_.TerminateAllBackends();
447*523fa7a6SAndroid Build Coastguard Worker }
448*523fa7a6SAndroid Build Coastguard Worker 
IsNodeSupportedByBackend(std::vector<std::shared_ptr<OpWrapper>> & op_wrappers)449*523fa7a6SAndroid Build Coastguard Worker bool QnnManager::IsNodeSupportedByBackend(
450*523fa7a6SAndroid Build Coastguard Worker     std::vector<std::shared_ptr<OpWrapper>>& op_wrappers) {
451*523fa7a6SAndroid Build Coastguard Worker   Qnn_ErrorHandle_t error = QNN_SUCCESS;
452*523fa7a6SAndroid Build Coastguard Worker 
453*523fa7a6SAndroid Build Coastguard Worker   for (std::shared_ptr<OpWrapper>& op_wrapper : op_wrappers) {
454*523fa7a6SAndroid Build Coastguard Worker     for (const auto& param : op_wrapper->GetParams()) {
455*523fa7a6SAndroid Build Coastguard Worker       // unused?
456*523fa7a6SAndroid Build Coastguard Worker       // auto* p_tensor_param = dynamic_cast<TensorParamWrapper*>(param.get());
457*523fa7a6SAndroid Build Coastguard Worker       if (param->PopulateQnnParam() != Error::Ok) {
458*523fa7a6SAndroid Build Coastguard Worker         QNN_EXECUTORCH_LOG_WARN(
459*523fa7a6SAndroid Build Coastguard Worker             "Qnn Backend op validation failed "
460*523fa7a6SAndroid Build Coastguard Worker             "with PopulateQnnParam: %d",
461*523fa7a6SAndroid Build Coastguard Worker             QNN_GET_ERROR_CODE(error));
462*523fa7a6SAndroid Build Coastguard Worker         return false;
463*523fa7a6SAndroid Build Coastguard Worker       }
464*523fa7a6SAndroid Build Coastguard Worker     }
465*523fa7a6SAndroid Build Coastguard Worker 
466*523fa7a6SAndroid Build Coastguard Worker     error = backend_params_ptr_->qnn_backend_ptr_->BackendValidateOpConfig(
467*523fa7a6SAndroid Build Coastguard Worker         op_wrapper->GetOpConfig());
468*523fa7a6SAndroid Build Coastguard Worker     if (error != QNN_SUCCESS) {
469*523fa7a6SAndroid Build Coastguard Worker       QNN_EXECUTORCH_LOG_WARN(
470*523fa7a6SAndroid Build Coastguard Worker           "Qnn Backend op validation failed with error: %d",
471*523fa7a6SAndroid Build Coastguard Worker           QNN_GET_ERROR_CODE(error));
472*523fa7a6SAndroid Build Coastguard Worker 
473*523fa7a6SAndroid Build Coastguard Worker       return false;
474*523fa7a6SAndroid Build Coastguard Worker     }
475*523fa7a6SAndroid Build Coastguard Worker   }
476*523fa7a6SAndroid Build Coastguard Worker   return true;
477*523fa7a6SAndroid Build Coastguard Worker }
478*523fa7a6SAndroid Build Coastguard Worker 
GetContextBinary(QnnExecuTorchContextBinary & qnn_executorch_context_binary)479*523fa7a6SAndroid Build Coastguard Worker Error QnnManager::GetContextBinary(
480*523fa7a6SAndroid Build Coastguard Worker     QnnExecuTorchContextBinary& qnn_executorch_context_binary) {
481*523fa7a6SAndroid Build Coastguard Worker   ET_CHECK_OR_RETURN_ERROR(
482*523fa7a6SAndroid Build Coastguard Worker       backend_params_ptr_->qnn_context_ptr_->GetContextBinary(
483*523fa7a6SAndroid Build Coastguard Worker           qnn_executorch_context_binary) == Error::Ok,
484*523fa7a6SAndroid Build Coastguard Worker       Internal,
485*523fa7a6SAndroid Build Coastguard Worker       "Fail to get context binary.");
486*523fa7a6SAndroid Build Coastguard Worker 
487*523fa7a6SAndroid Build Coastguard Worker   return Error::Ok;
488*523fa7a6SAndroid Build Coastguard Worker }
489*523fa7a6SAndroid Build Coastguard Worker 
CompileQcir()490*523fa7a6SAndroid Build Coastguard Worker Error QnnManager::CompileQcir() {
491*523fa7a6SAndroid Build Coastguard Worker   flatbuffers::Verifier verifier_binary_info(
492*523fa7a6SAndroid Build Coastguard Worker       static_cast<const uint8_t* const>(qnn_context_blob_.buffer),
493*523fa7a6SAndroid Build Coastguard Worker       qnn_context_blob_.nbytes);
494*523fa7a6SAndroid Build Coastguard Worker   if (!qnn_delegate::VerifyBinaryInfoBuffer(verifier_binary_info)) {
495*523fa7a6SAndroid Build Coastguard Worker     QNN_EXECUTORCH_LOG_ERROR("Fail to verify binary info");
496*523fa7a6SAndroid Build Coastguard Worker     return Error::Internal;
497*523fa7a6SAndroid Build Coastguard Worker   }
498*523fa7a6SAndroid Build Coastguard Worker 
499*523fa7a6SAndroid Build Coastguard Worker   auto binary_info = qnn_delegate::GetBinaryInfo(qnn_context_blob_.buffer);
500*523fa7a6SAndroid Build Coastguard Worker   flatbuffers::Verifier verifier_qcir(
501*523fa7a6SAndroid Build Coastguard Worker       binary_info->data()->data(), binary_info->data()->size());
502*523fa7a6SAndroid Build Coastguard Worker   if (!qcir::VerifyContextBuffer(verifier_qcir)) {
503*523fa7a6SAndroid Build Coastguard Worker     QNN_EXECUTORCH_LOG_ERROR("Fail to verify qcir format");
504*523fa7a6SAndroid Build Coastguard Worker     return Error::Internal;
505*523fa7a6SAndroid Build Coastguard Worker   }
506*523fa7a6SAndroid Build Coastguard Worker 
507*523fa7a6SAndroid Build Coastguard Worker   auto context = qcir::GetContext(binary_info->data()->data());
508*523fa7a6SAndroid Build Coastguard Worker   for (const auto& graph : *context->graphs()) {
509*523fa7a6SAndroid Build Coastguard Worker     // qcir tensors to TensorWrapper
510*523fa7a6SAndroid Build Coastguard Worker     std::vector<std::shared_ptr<TensorWrapper>> graph_inputs, graph_outputs,
511*523fa7a6SAndroid Build Coastguard Worker         tensors;
512*523fa7a6SAndroid Build Coastguard Worker     for (const auto& tensor : *graph->tensors()) {
513*523fa7a6SAndroid Build Coastguard Worker       tensors.emplace_back(CreateTensorWrapper(ToTensor(tensor)));
514*523fa7a6SAndroid Build Coastguard Worker       if (tensor->type() == qcir::TensorType::WRITE) {
515*523fa7a6SAndroid Build Coastguard Worker         graph_inputs.push_back(tensors.back());
516*523fa7a6SAndroid Build Coastguard Worker       } else if (tensor->type() == qcir::TensorType::READ) {
517*523fa7a6SAndroid Build Coastguard Worker         graph_outputs.push_back(tensors.back());
518*523fa7a6SAndroid Build Coastguard Worker       }
519*523fa7a6SAndroid Build Coastguard Worker     }
520*523fa7a6SAndroid Build Coastguard Worker     std::vector<std::shared_ptr<OpWrapper>> op_wrappers;
521*523fa7a6SAndroid Build Coastguard Worker     // qcir graph node to OpWrapper
522*523fa7a6SAndroid Build Coastguard Worker     for (const auto& node : *graph->nodes()) {
523*523fa7a6SAndroid Build Coastguard Worker       std::shared_ptr<OpWrapper> op = std::make_shared<OpWrapper>(
524*523fa7a6SAndroid Build Coastguard Worker           node->name()->str(),
525*523fa7a6SAndroid Build Coastguard Worker           node->package_name()->str(),
526*523fa7a6SAndroid Build Coastguard Worker           node->type_name()->str());
527*523fa7a6SAndroid Build Coastguard Worker 
528*523fa7a6SAndroid Build Coastguard Worker       // qcir input tensors to OpWrapper input tensors
529*523fa7a6SAndroid Build Coastguard Worker       std::vector<std::shared_ptr<TensorWrapper>> inputs;
530*523fa7a6SAndroid Build Coastguard Worker       for (uint32_t index : *node->inputs()) {
531*523fa7a6SAndroid Build Coastguard Worker         inputs.push_back(tensors[index]);
532*523fa7a6SAndroid Build Coastguard Worker       }
533*523fa7a6SAndroid Build Coastguard Worker       op->AddInputTensors(inputs);
534*523fa7a6SAndroid Build Coastguard Worker 
535*523fa7a6SAndroid Build Coastguard Worker       // qcir output tensors to OpWrapper output tensors
536*523fa7a6SAndroid Build Coastguard Worker       std::vector<std::shared_ptr<TensorWrapper>> outputs;
537*523fa7a6SAndroid Build Coastguard Worker       for (uint32_t index : *node->outputs()) {
538*523fa7a6SAndroid Build Coastguard Worker         outputs.push_back(tensors[index]);
539*523fa7a6SAndroid Build Coastguard Worker       }
540*523fa7a6SAndroid Build Coastguard Worker       op->AddOutputTensors(outputs);
541*523fa7a6SAndroid Build Coastguard Worker 
542*523fa7a6SAndroid Build Coastguard Worker       // qcir operator param to OpWrapper param
543*523fa7a6SAndroid Build Coastguard Worker       for (uint32_t index : *node->params()) {
544*523fa7a6SAndroid Build Coastguard Worker         const auto& tensor = graph->tensors()->Get(index);
545*523fa7a6SAndroid Build Coastguard Worker         std::string name = tensor->name()->str();
546*523fa7a6SAndroid Build Coastguard Worker         Qnn_DataType_t dtype = ToDataType(tensor->dtype());
547*523fa7a6SAndroid Build Coastguard Worker         if (tensor->shape()->size() != 0) {
548*523fa7a6SAndroid Build Coastguard Worker           // add tensor param
549*523fa7a6SAndroid Build Coastguard Worker           op->AddTensorParam(
550*523fa7a6SAndroid Build Coastguard Worker               name,
551*523fa7a6SAndroid Build Coastguard Worker               dtype,
552*523fa7a6SAndroid Build Coastguard Worker               tensor->shape()->size(),
553*523fa7a6SAndroid Build Coastguard Worker               tensor->shape()->data(),
554*523fa7a6SAndroid Build Coastguard Worker               tensor->data()->data());
555*523fa7a6SAndroid Build Coastguard Worker         } else {
556*523fa7a6SAndroid Build Coastguard Worker           // add scalar param
557*523fa7a6SAndroid Build Coastguard Worker           switch (dtype) {
558*523fa7a6SAndroid Build Coastguard Worker             case Qnn_DataType_t::QNN_DATATYPE_INT_32:
559*523fa7a6SAndroid Build Coastguard Worker               op->AddScalarParam(
560*523fa7a6SAndroid Build Coastguard Worker                   name,
561*523fa7a6SAndroid Build Coastguard Worker                   dtype,
562*523fa7a6SAndroid Build Coastguard Worker                   *reinterpret_cast<const int32_t*>(tensor->data()->Data()));
563*523fa7a6SAndroid Build Coastguard Worker               break;
564*523fa7a6SAndroid Build Coastguard Worker             case Qnn_DataType_t::QNN_DATATYPE_INT_16:
565*523fa7a6SAndroid Build Coastguard Worker               op->AddScalarParam(
566*523fa7a6SAndroid Build Coastguard Worker                   name,
567*523fa7a6SAndroid Build Coastguard Worker                   dtype,
568*523fa7a6SAndroid Build Coastguard Worker                   *reinterpret_cast<const int16_t*>(tensor->data()->Data()));
569*523fa7a6SAndroid Build Coastguard Worker               break;
570*523fa7a6SAndroid Build Coastguard Worker             case Qnn_DataType_t::QNN_DATATYPE_INT_8:
571*523fa7a6SAndroid Build Coastguard Worker               op->AddScalarParam(
572*523fa7a6SAndroid Build Coastguard Worker                   name, dtype, static_cast<int8_t>(*tensor->data()->Data()));
573*523fa7a6SAndroid Build Coastguard Worker               break;
574*523fa7a6SAndroid Build Coastguard Worker             case Qnn_DataType_t::QNN_DATATYPE_UINT_32:
575*523fa7a6SAndroid Build Coastguard Worker               op->AddScalarParam(
576*523fa7a6SAndroid Build Coastguard Worker                   name,
577*523fa7a6SAndroid Build Coastguard Worker                   dtype,
578*523fa7a6SAndroid Build Coastguard Worker                   *reinterpret_cast<const uint32_t*>(tensor->data()->Data()));
579*523fa7a6SAndroid Build Coastguard Worker               break;
580*523fa7a6SAndroid Build Coastguard Worker             case Qnn_DataType_t::QNN_DATATYPE_UINT_16:
581*523fa7a6SAndroid Build Coastguard Worker               op->AddScalarParam(
582*523fa7a6SAndroid Build Coastguard Worker                   name,
583*523fa7a6SAndroid Build Coastguard Worker                   dtype,
584*523fa7a6SAndroid Build Coastguard Worker                   *reinterpret_cast<const uint16_t*>(tensor->data()->Data()));
585*523fa7a6SAndroid Build Coastguard Worker               break;
586*523fa7a6SAndroid Build Coastguard Worker             case Qnn_DataType_t::QNN_DATATYPE_UINT_8:
587*523fa7a6SAndroid Build Coastguard Worker               op->AddScalarParam(name, dtype, *tensor->data()->Data());
588*523fa7a6SAndroid Build Coastguard Worker               break;
589*523fa7a6SAndroid Build Coastguard Worker             case Qnn_DataType_t::QNN_DATATYPE_FLOAT_32:
590*523fa7a6SAndroid Build Coastguard Worker             case Qnn_DataType_t::QNN_DATATYPE_FLOAT_16:
591*523fa7a6SAndroid Build Coastguard Worker               op->AddScalarParam(
592*523fa7a6SAndroid Build Coastguard Worker                   name,
593*523fa7a6SAndroid Build Coastguard Worker                   dtype,
594*523fa7a6SAndroid Build Coastguard Worker                   *reinterpret_cast<const float*>(tensor->data()->Data()));
595*523fa7a6SAndroid Build Coastguard Worker               break;
596*523fa7a6SAndroid Build Coastguard Worker             case Qnn_DataType_t::QNN_DATATYPE_BOOL_8:
597*523fa7a6SAndroid Build Coastguard Worker               op->AddScalarParam(name, dtype, *tensor->data()->Data());
598*523fa7a6SAndroid Build Coastguard Worker               break;
599*523fa7a6SAndroid Build Coastguard Worker             default:
600*523fa7a6SAndroid Build Coastguard Worker               QNN_EXECUTORCH_LOG_ERROR(
601*523fa7a6SAndroid Build Coastguard Worker                   "Invalid scalar type: %s", tensor->name()->c_str());
602*523fa7a6SAndroid Build Coastguard Worker               break;
603*523fa7a6SAndroid Build Coastguard Worker           }
604*523fa7a6SAndroid Build Coastguard Worker         }
605*523fa7a6SAndroid Build Coastguard Worker       }
606*523fa7a6SAndroid Build Coastguard Worker       op_wrappers.push_back(std::move(op));
607*523fa7a6SAndroid Build Coastguard Worker     }
608*523fa7a6SAndroid Build Coastguard Worker 
609*523fa7a6SAndroid Build Coastguard Worker     ET_CHECK_OR_RETURN_ERROR(
610*523fa7a6SAndroid Build Coastguard Worker         Compile(graph->name()->str(), op_wrappers) == Error::Ok,
611*523fa7a6SAndroid Build Coastguard Worker         Internal,
612*523fa7a6SAndroid Build Coastguard Worker         "Fail to compile graph from qcir with graph_name: %s",
613*523fa7a6SAndroid Build Coastguard Worker         graph->name()->str().c_str());
614*523fa7a6SAndroid Build Coastguard Worker 
615*523fa7a6SAndroid Build Coastguard Worker     ET_CHECK_OR_RETURN_ERROR(
616*523fa7a6SAndroid Build Coastguard Worker         AllocateTensor(graph->name()->str(), graph_inputs, graph_outputs) ==
617*523fa7a6SAndroid Build Coastguard Worker             Error::Ok,
618*523fa7a6SAndroid Build Coastguard Worker         Internal,
619*523fa7a6SAndroid Build Coastguard Worker         "Fail to allocate tensor for qcir with graph_name: %s",
620*523fa7a6SAndroid Build Coastguard Worker         graph->name()->str().c_str());
621*523fa7a6SAndroid Build Coastguard Worker   }
622*523fa7a6SAndroid Build Coastguard Worker 
623*523fa7a6SAndroid Build Coastguard Worker   return Error::Ok;
624*523fa7a6SAndroid Build Coastguard Worker }
625*523fa7a6SAndroid Build Coastguard Worker 
Compile(const std::string & graph_name,std::vector<std::shared_ptr<OpWrapper>> & op_wrappers)626*523fa7a6SAndroid Build Coastguard Worker Error QnnManager::Compile(
627*523fa7a6SAndroid Build Coastguard Worker     const std::string& graph_name,
628*523fa7a6SAndroid Build Coastguard Worker     std::vector<std::shared_ptr<OpWrapper>>& op_wrappers) {
629*523fa7a6SAndroid Build Coastguard Worker   Qnn_ErrorHandle_t error = QNN_SUCCESS;
630*523fa7a6SAndroid Build Coastguard Worker 
631*523fa7a6SAndroid Build Coastguard Worker   for (std::shared_ptr<OpWrapper>& op_wrapper : op_wrappers) {
632*523fa7a6SAndroid Build Coastguard Worker     for (const auto& tensor_wrapper : op_wrapper->GetInputTensors()) {
633*523fa7a6SAndroid Build Coastguard Worker       ET_CHECK_OR_RETURN_ERROR(
634*523fa7a6SAndroid Build Coastguard Worker           backend_params_ptr_->qnn_graph_ptr_->EnsureTensorInQnnGraph(
635*523fa7a6SAndroid Build Coastguard Worker               graph_name, tensor_wrapper) == Error::Ok,
636*523fa7a6SAndroid Build Coastguard Worker           Internal,
637*523fa7a6SAndroid Build Coastguard Worker           "Tensor name %s isn't added to Qnn Graph",
638*523fa7a6SAndroid Build Coastguard Worker           tensor_wrapper->GetName().c_str());
639*523fa7a6SAndroid Build Coastguard Worker     }
640*523fa7a6SAndroid Build Coastguard Worker 
641*523fa7a6SAndroid Build Coastguard Worker     for (const auto& tensor_wrapper : op_wrapper->GetOutputTensors()) {
642*523fa7a6SAndroid Build Coastguard Worker       ET_CHECK_OR_RETURN_ERROR(
643*523fa7a6SAndroid Build Coastguard Worker           backend_params_ptr_->qnn_graph_ptr_->EnsureTensorInQnnGraph(
644*523fa7a6SAndroid Build Coastguard Worker               graph_name, tensor_wrapper) == Error::Ok,
645*523fa7a6SAndroid Build Coastguard Worker           Internal,
646*523fa7a6SAndroid Build Coastguard Worker           "Tensor name %s isn't added to Qnn Graph",
647*523fa7a6SAndroid Build Coastguard Worker           tensor_wrapper->GetName().c_str());
648*523fa7a6SAndroid Build Coastguard Worker     }
649*523fa7a6SAndroid Build Coastguard Worker 
650*523fa7a6SAndroid Build Coastguard Worker     for (const auto& param : op_wrapper->GetParams()) {
651*523fa7a6SAndroid Build Coastguard Worker       auto* p_tensor_param = dynamic_cast<TensorParamWrapper*>(param.get());
652*523fa7a6SAndroid Build Coastguard Worker       if (p_tensor_param != nullptr) {
653*523fa7a6SAndroid Build Coastguard Worker         ET_CHECK_OR_RETURN_ERROR(
654*523fa7a6SAndroid Build Coastguard Worker             backend_params_ptr_->qnn_graph_ptr_->EnsureTensorInQnnGraph(
655*523fa7a6SAndroid Build Coastguard Worker                 graph_name, p_tensor_param->GetTensorWrapper()) == Error::Ok,
656*523fa7a6SAndroid Build Coastguard Worker             Internal,
657*523fa7a6SAndroid Build Coastguard Worker             "Param tensor name %s isn't added to Qnn Graph",
658*523fa7a6SAndroid Build Coastguard Worker             p_tensor_param->GetName().c_str());
659*523fa7a6SAndroid Build Coastguard Worker       }
660*523fa7a6SAndroid Build Coastguard Worker       ET_CHECK_OR_RETURN_ERROR(
661*523fa7a6SAndroid Build Coastguard Worker           param->PopulateQnnParam() == Error::Ok,
662*523fa7a6SAndroid Build Coastguard Worker           Internal,
663*523fa7a6SAndroid Build Coastguard Worker           "Fail to configure Qnn backend");
664*523fa7a6SAndroid Build Coastguard Worker     }
665*523fa7a6SAndroid Build Coastguard Worker 
666*523fa7a6SAndroid Build Coastguard Worker     error = backend_params_ptr_->qnn_graph_ptr_->GraphAddNode(
667*523fa7a6SAndroid Build Coastguard Worker         graph_name, op_wrapper->GetOpConfig());
668*523fa7a6SAndroid Build Coastguard Worker     if (error != QNN_SUCCESS) {
669*523fa7a6SAndroid Build Coastguard Worker       QNN_EXECUTORCH_LOG_ERROR(
670*523fa7a6SAndroid Build Coastguard Worker           "Failed to add node to Qnn Graph with error: %d",
671*523fa7a6SAndroid Build Coastguard Worker           QNN_GET_ERROR_CODE(error));
672*523fa7a6SAndroid Build Coastguard Worker       return Error::Internal;
673*523fa7a6SAndroid Build Coastguard Worker     }
674*523fa7a6SAndroid Build Coastguard Worker   }
675*523fa7a6SAndroid Build Coastguard Worker 
676*523fa7a6SAndroid Build Coastguard Worker   error = backend_params_ptr_->qnn_graph_ptr_->GraphFinalize(graph_name);
677*523fa7a6SAndroid Build Coastguard Worker   if (error != QNN_SUCCESS) {
678*523fa7a6SAndroid Build Coastguard Worker     QNN_EXECUTORCH_LOG_ERROR(
679*523fa7a6SAndroid Build Coastguard Worker         "Failed to finalize Qnn Graph with error: %d",
680*523fa7a6SAndroid Build Coastguard Worker         QNN_GET_ERROR_CODE(error));
681*523fa7a6SAndroid Build Coastguard Worker     return Error::Internal;
682*523fa7a6SAndroid Build Coastguard Worker   }
683*523fa7a6SAndroid Build Coastguard Worker 
684*523fa7a6SAndroid Build Coastguard Worker   return Error::Ok;
685*523fa7a6SAndroid Build Coastguard Worker }
686*523fa7a6SAndroid Build Coastguard Worker 
GetBinarySignature()687*523fa7a6SAndroid Build Coastguard Worker std::string QnnManager::GetBinarySignature() {
688*523fa7a6SAndroid Build Coastguard Worker   flatbuffers::Verifier verifier(
689*523fa7a6SAndroid Build Coastguard Worker       static_cast<const uint8_t* const>(qnn_context_blob_.buffer),
690*523fa7a6SAndroid Build Coastguard Worker       qnn_context_blob_.nbytes);
691*523fa7a6SAndroid Build Coastguard Worker   return VerifyBinaryInfoBuffer(verifier)
692*523fa7a6SAndroid Build Coastguard Worker       ? GetBinaryInfo(qnn_context_blob_.buffer)->signature()->str()
693*523fa7a6SAndroid Build Coastguard Worker       : "";
694*523fa7a6SAndroid Build Coastguard Worker }
695*523fa7a6SAndroid Build Coastguard Worker 
696*523fa7a6SAndroid Build Coastguard Worker } // namespace qnn
697*523fa7a6SAndroid Build Coastguard Worker } // namespace backends
698*523fa7a6SAndroid Build Coastguard Worker } // namespace executorch
QnnExecuTorchAllocCustomMem(size_t bytes,size_t alignment)699*523fa7a6SAndroid Build Coastguard Worker void* QnnExecuTorchAllocCustomMem(size_t bytes, size_t alignment) {
700*523fa7a6SAndroid Build Coastguard Worker   void* buffer_ptr =
701*523fa7a6SAndroid Build Coastguard Worker       executorch::backends::qnn::SharedBuffer::GetSharedBufferManager()
702*523fa7a6SAndroid Build Coastguard Worker           .AllocMem(bytes, alignment);
703*523fa7a6SAndroid Build Coastguard Worker   return buffer_ptr;
704*523fa7a6SAndroid Build Coastguard Worker }
705*523fa7a6SAndroid Build Coastguard Worker 
QnnExecuTorchFreeCustomMem(void * buffer_ptr)706*523fa7a6SAndroid Build Coastguard Worker void QnnExecuTorchFreeCustomMem(void* buffer_ptr) {
707*523fa7a6SAndroid Build Coastguard Worker   executorch::backends::qnn::SharedBuffer::GetSharedBufferManager().FreeMem(
708*523fa7a6SAndroid Build Coastguard Worker       buffer_ptr);
709*523fa7a6SAndroid Build Coastguard Worker }
710*523fa7a6SAndroid Build Coastguard Worker 
QnnExecuTorchAddCustomMemTensorAddr(void * tensor_addr,void * custom_mem)711*523fa7a6SAndroid Build Coastguard Worker void QnnExecuTorchAddCustomMemTensorAddr(void* tensor_addr, void* custom_mem) {
712*523fa7a6SAndroid Build Coastguard Worker   executorch::backends::qnn::SharedBuffer::GetSharedBufferManager()
713*523fa7a6SAndroid Build Coastguard Worker       .AddCusomMemTensorAddr(tensor_addr, custom_mem);
714*523fa7a6SAndroid Build Coastguard Worker }
715*523fa7a6SAndroid Build Coastguard Worker 
QnnExecuTorchAddCustomMemTensorInfo(const CustomMemTensorInfo & info)716*523fa7a6SAndroid Build Coastguard Worker void QnnExecuTorchAddCustomMemTensorInfo(const CustomMemTensorInfo& info) {
717*523fa7a6SAndroid Build Coastguard Worker   executorch::backends::qnn::SharedBuffer::GetSharedBufferManager()
718*523fa7a6SAndroid Build Coastguard Worker       .AddCusomMemTensorInfo(info);
719*523fa7a6SAndroid Build Coastguard Worker }
720