Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 64 additions & 0 deletions backends/samsung/BUCK
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
load("@fbcode_macros//build_defs:build_file_migration.bzl", "fbcode_target")
load("@fbcode_macros//build_defs:python_unittest.bzl", "python_unittest")
load("@fbsource//xplat/executorch/build:runtime_wrapper.bzl", "runtime")

oncall("executorch")

fbcode_target(
_kind = runtime.python_library,
name = "aot_sdk_unbound",
srcs = ["enn_preprocess.py"] + glob([
"_passes/*.py",
"builders/*.py",
"partition/*.py",
"quantizer/*.py",
"serialization/*.py",
"utils/*.py",
]),
resources = ["serialization/compile_options_def.fbs"],
labels = ["noautodeps"],
visibility = ["PUBLIC"],
deps = [
"fbsource//third-party/pypi/numpy:numpy",
"//caffe2:torch",
"//executorch/backends/transforms:addmm_mm_to_linear",
"//executorch/backends/transforms:decompose_sdpa",
"//executorch/backends/transforms:fuse_batch_norm_with_conv",
"//executorch/backends/transforms:lib",
"//executorch/backends/transforms:remove_clone_ops",
"//executorch/backends/transforms:remove_getitem_op",
"//executorch/backends/transforms:utils",
"//executorch/exir:_warnings",
"//executorch/exir:lib",
"//executorch/exir:pass_base",
"//executorch/exir:pass_manager",
"//executorch/exir:sym_util",
"//executorch/exir/_serialize:lib",
"//executorch/exir/backend:backend_details",
"//executorch/exir/backend:compile_spec_schema",
"//executorch/exir/backend:partitioner",
"//executorch/exir/backend:utils",
"//executorch/exir/backend/canonical_partitioners:canonical_partitioner_lib",
"//executorch/exir/dialects:lib",
"//executorch/exir/dialects/edge:lib",
"//executorch/exir/passes:constant_prop_pass",
"//executorch/exir/passes:lib",
"//executorch/exir/program:program",
"//pytorch/ao:torchao",
],
)

fbcode_target(
_kind = python_unittest,
name = "compile_options_test",
srcs = [
"serialization/compile_options.py",
"test/test_compile_options.py",
],
resources = ["serialization/compile_options_def.fbs"],
deps = [
"//executorch/exir:_warnings",
"//executorch/exir/_serialize:lib",
"//executorch/exir/backend:compile_spec_schema",
],
)
52 changes: 52 additions & 0 deletions backends/samsung/runtime/BUCK
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Any targets that should be shared between fbcode and xplat must be defined in
# targets.bzl. This file can contain xplat-only targets.

load(
"@fbsource//tools/build_defs:default_platform_defs.bzl",
"ANDROID",
)
load("@fbcode_macros//build_defs:build_file_migration.bzl", "non_fbcode_target")
load("@fbsource//xplat/executorch/build:runtime_wrapper.bzl", "runtime")

oncall("executorch")

non_fbcode_target(
_kind = runtime.cxx_test,
name = "enn_executor_allocator_test",
srcs = [
"test/enn_executor_allocator_test.cpp",
],
headers = glob([
"*.h",
"*.hpp",
]),
deps = [
"//executorch/runtime/core:memory_allocator",
],
)

non_fbcode_target(
_kind = runtime.cxx_library,
name = "enn_backend",
srcs = [
"enn_api_implementation.cpp",
"enn_backend.cpp",
"enn_executor.cpp",
"enn_shared_memory_manager.cpp",
"logging.cpp",
],
headers = glob([
"*.h",
"*.hpp",
]),
modifiers = ["ovr_config//os/version/android/constraints:api-level-26"],
deps = [
"//executorch/runtime/backend:interface",
"//executorch/runtime/core:memory_allocator",
"//third-party/toolchains:dl",
],
define_static_target = True,
link_whole = True,
platforms = [ANDROID],
visibility = ["PUBLIC"],
)
2 changes: 2 additions & 0 deletions backends/samsung/runtime/enn_api_implementation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ Error EnnApi::loadApiLib() {
ENN_LOAD_API_FUNC(libenn_public_api_, EnnAllocateAllBuffers, this);
ENN_LOAD_API_FUNC(
libenn_public_api_, EnnAllocateAllBuffersWithSessionId, this);
EnnGenerateBufferSpaceDev = reinterpret_cast<EnnGenerateBufferSpaceDev_fn>(
loadApiFunction(libenn_public_api_, "EnnGenerateBufferSpaceDev", true));
ENN_LOAD_API_FUNC(libenn_public_api_, EnnBufferCommit, this);
ENN_LOAD_API_FUNC(libenn_public_api_, EnnGetBuffersInfo, this);
ENN_LOAD_API_FUNC(libenn_public_api_, EnnReleaseBuffers, this);
Expand Down
59 changes: 30 additions & 29 deletions backends/samsung/runtime/enn_api_implementation.h
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
/*
* Copyright (c) 2025 Samsung Electronics Co. LTD
* All rights reserved
Expand All @@ -12,8 +12,6 @@

#include <atomic>
#include <cstdint>
#include <memory>
#include <mutex>

namespace torch {
namespace executor {
Expand Down Expand Up @@ -60,6 +58,9 @@
NumberOfBuffersInfo* out_buffers_info,
const int session_id,
const bool do_commit);
EnnReturn (*EnnGenerateBufferSpaceDev)(
const EnnModelId model_id,
const int session_count);
EnnReturn (*EnnExecuteModelWithSessionIdWait)(
const EnnModelId model_id,
const int session_id);
Expand All @@ -78,64 +79,64 @@
*EnnGetFileDescriptorFromEnnBuffer)(EnnBufferPtr buffer, int32_t* fd);

private:
static std::mutex instance_mutex_;
std::atomic_bool initialize_ = false;
// Pointer to the dlopen libs
void* libenn_public_api_ = nullptr;
static std::atomic<int> ref_count_;

EnnApi();
Error loadApiLib();
Error unloadApiLib();
};

typedef EnnReturn (*EnnInitialize_fn)(void);
typedef EnnReturn (*EnnSetPreferencePerfMode_fn)(const uint32_t val);
typedef EnnReturn (*EnnGetPreferencePerfMode_fn)(uint32_t* val_ptr);
typedef EnnReturn (
*EnnOpenModel_fn)(const char* model_file, EnnModelId* model_id);
typedef EnnReturn (*EnnOpenModelFromMemory_fn)(
using EnnInitialize_fn = EnnReturn (*)(void);
using EnnSetPreferencePerfMode_fn = EnnReturn (*)(const uint32_t val);
using EnnGetPreferencePerfMode_fn = EnnReturn (*)(uint32_t* val_ptr);
using EnnOpenModel_fn =
EnnReturn (*)(const char* model_file, EnnModelId* model_id);
using EnnOpenModelFromMemory_fn = EnnReturn (*)(
const char* va,
const uint32_t size,
EnnModelId* model_id);
typedef EnnReturn (*EnnSetFastIpc_fn)(void);
typedef EnnReturn (*EnnUnsetFastIpc_fn)(void);
typedef EnnReturn (*EnnExecuteModelFastIpc_fn)(
using EnnSetFastIpc_fn = EnnReturn (*)(void);
using EnnUnsetFastIpc_fn = EnnReturn (*)(void);
using EnnExecuteModelFastIpc_fn = EnnReturn (*)(
const EnnModelId model_id,
int client_sleep_usec);
typedef EnnReturn (*EnnExecuteModel_fn)(const EnnModelId model_id);
typedef EnnReturn (*EnnExecuteModelWithSessionIdAsync_fn)(
using EnnExecuteModel_fn = EnnReturn (*)(const EnnModelId model_id);
using EnnExecuteModelWithSessionIdAsync_fn = EnnReturn (*)(
const EnnModelId model_id,
const int session_id);
typedef EnnReturn (*EnnCloseModel_fn)(const EnnModelId model_id);
typedef EnnReturn (*EnnDeinitialize_fn)(void);
typedef EnnReturn (*EnnAllocateAllBuffers_fn)(
using EnnCloseModel_fn = EnnReturn (*)(const EnnModelId model_id);
using EnnDeinitialize_fn = EnnReturn (*)(void);
using EnnAllocateAllBuffers_fn = EnnReturn (*)(
const EnnModelId model_id,
EnnBufferPtr** out_buffers,
NumberOfBuffersInfo* out_buffers_info);
typedef EnnReturn (*EnnAllocateAllBuffersWithSessionId_fn)(
using EnnAllocateAllBuffersWithSessionId_fn = EnnReturn (*)(
const EnnModelId model_id,
EnnBufferPtr** out_buffers,
NumberOfBuffersInfo* out_buffers_info,
const int session_id,
const bool do_commit);
typedef EnnReturn (*EnnExecuteModelWithSessionIdWait_fn)(
using EnnGenerateBufferSpaceDev_fn =
EnnReturn (*)(const EnnModelId model_id, const int session_count);
using EnnExecuteModelWithSessionIdWait_fn = EnnReturn (*)(
const EnnModelId model_id,
const int session_id);
typedef EnnReturn (*EnnBufferCommit_fn)(const EnnModelId model_id);
typedef EnnReturn (*EnnGetBuffersInfo_fn)(
using EnnBufferCommit_fn = EnnReturn (*)(const EnnModelId model_id);
using EnnGetBuffersInfo_fn = EnnReturn (*)(
const EnnModelId model_id,
NumberOfBuffersInfo* buffers_info);
typedef EnnReturn (
*EnnReleaseBuffers_fn)(EnnBufferPtr* buffers, const int32_t numOfBuffers);
typedef EnnReturn (*EnnCreateBuffer_fn)(
using EnnReleaseBuffers_fn =
EnnReturn (*)(EnnBufferPtr* buffers, const int32_t numOfBuffers);
using EnnCreateBuffer_fn = EnnReturn (*)(
const uint32_t req_size,
const uint32_t ion_flag,
EnnBufferPtr* out);
typedef EnnReturn (*EnnReleaseBuffer_fn)(EnnBufferPtr buf);
typedef EnnReturn (
*EnnGetFileDescriptorFromEnnBuffer_fn)(EnnBufferPtr buffer, int32_t* fd);
typedef EnnReturn (*EnnOpenModelFromFd_fn)(int _fd, EnnModelId* model_id);
using EnnReleaseBuffer_fn = EnnReturn (*)(EnnBufferPtr buf);
using EnnGetFileDescriptorFromEnnBuffer_fn =
EnnReturn (*)(EnnBufferPtr buffer, int32_t* fd);
using EnnOpenModelFromFd_fn = EnnReturn (*)(int _fd, EnnModelId* model_id);

} // namespace enn
} // namespace executor
Expand Down
10 changes: 8 additions & 2 deletions backends/samsung/runtime/enn_backend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* LICENSE file in the root directory of this source tree.
*
*/
#include <executorch/backends/samsung/runtime/enn_executor.h>
#include <executorch/backends/samsung/runtime/enn_executor_allocator.h>
#include <executorch/backends/samsung/runtime/logging.h>
#include <executorch/backends/samsung/runtime/profile.hpp>

Expand Down Expand Up @@ -37,7 +37,13 @@ class EnnBackend final : public PyTorchBackendInterface {
ArrayRef<CompileSpec> compile_specs) const override {
EXYNOS_ATRACE_NAME_LINE("backend_init");
MemoryAllocator* runtime_allocator = context.get_runtime_allocator();
auto executor = runtime_allocator->allocateInstance<enn::EnnExecutor>();
if (runtime_allocator == nullptr) {
return Error::MemoryAllocationFailed;
}
auto* executor = enn::allocateEnnExecutor(*runtime_allocator);
if (executor == nullptr) {
return Error::MemoryAllocationFailed;
}
const char* binary_buf_addr =
reinterpret_cast<const char*>(processed->data());
size_t buf_size = processed->size();
Expand Down
23 changes: 19 additions & 4 deletions backends/samsung/runtime/enn_executor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,17 @@ Error EnnExecutor::initialize(const char* binary_buf_addr, size_t buf_size) {
(int)ret);
ET_LOG(Info, "Open successfully.");

if (enn_api_inst->EnnGenerateBufferSpaceDev != nullptr) {
ret = enn_api_inst->EnnGenerateBufferSpaceDev(model_id_, 1);
if (ret != ENN_RET_SUCCESS) {
ENN_LOG_WARN(
"EnnGenerateBufferSpaceDev returned %d for model_id = 0x%" PRIX64
"; continuing with session 0",
(int)ret,
model_id_);
}
}

NumberOfBuffersInfo buffers_info;
ret = enn_api_inst->EnnAllocateAllBuffersWithSessionId(
model_id_, &alloc_buffer_, &buffers_info, 0, true);
Expand All @@ -76,13 +87,13 @@ Error EnnExecutor::eval(
ET_CHECK_OR_RETURN_ERROR(
inputs.size() == getInputSize(),
InvalidArgument,
"Invalid number of inputs, expect %" PRIu32 " while get %ld",
"Invalid number of inputs, expect %" PRIu32 " while get %zu",
getInputSize(),
inputs.size());
ET_CHECK_OR_RETURN_ERROR(
outputs.size() == getOutputSize(),
InvalidArgument,
"Invalid number of outputs, expected %" PRIu32 " while get %ld",
"Invalid number of outputs, expected %" PRIu32 " while get %zu",
getOutputSize(),
outputs.size());

Expand Down Expand Up @@ -116,9 +127,13 @@ Error EnnExecutor::eval(
EnnExecutor::~EnnExecutor() {
EXYNOS_ATRACE_FUNCTION_LINE();
const EnnApi* enn_api_inst = EnnApi::getEnnApiInstance();
if (!enn_api_inst->isInitialized() || model_id_ == 0) {
return;
}
NumberOfBuffersInfo buffers_info;
if (enn_api_inst->EnnGetBuffersInfo(model_id_, &buffers_info) ==
ENN_RET_SUCCESS) {
if (alloc_buffer_ != nullptr &&
enn_api_inst->EnnGetBuffersInfo(model_id_, &buffers_info) ==
ENN_RET_SUCCESS) {
const int32_t num_of_buffers =
buffers_info.n_in_buf + buffers_info.n_out_buf;
enn_api_inst->EnnReleaseBuffers(alloc_buffer_, num_of_buffers);
Expand Down
30 changes: 30 additions & 0 deletions backends/samsung/runtime/enn_executor_allocator.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Copyright (c) 2025 Samsung Electronics Co. LTD
* All rights reserved
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree.
*
*/
#pragma once

#include <executorch/backends/samsung/runtime/enn_executor.h>
#include <executorch/runtime/core/memory_allocator.h>

#include <new>

namespace torch {
namespace executor {
namespace enn {

inline EnnExecutor* allocateEnnExecutor(MemoryAllocator& allocator) {
auto* storage = allocator.allocateInstance<EnnExecutor>();
if (storage == nullptr) {
return nullptr;
}
return new (storage) EnnExecutor();
}

} // namespace enn
} // namespace executor
} // namespace torch
6 changes: 5 additions & 1 deletion backends/samsung/runtime/logging.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ void EnnLogImpl(ENN_LOG_LEVEL log_level, const char* format, ...) {
va_list args;
va_start(args, format);
#ifdef __ANDROID__
va_list android_args;
va_copy(android_args, args);
int android_severity = ANDROID_LOG_DEBUG;
switch (log_level) {
case ENN_LOG_LEVEL::DEBUG:
Expand All @@ -35,7 +37,9 @@ void EnnLogImpl(ENN_LOG_LEVEL log_level, const char* format, ...) {
android_severity = ANDROID_LOG_UNKNOWN;
break;
}
__android_log_print(android_severity, "[Exynos ExecuTorch]", format, args);
__android_log_vprint(
android_severity, "[Exynos ExecuTorch]", format, android_args);
va_end(android_args);
#endif
const char* serverity_name;
switch (log_level) {
Expand Down
Loading
Loading