diff --git a/projects/llm_framework/main_kws/SConstruct b/projects/llm_framework/main_kws/SConstruct index eb00040..fc02a37 100644 --- a/projects/llm_framework/main_kws/SConstruct +++ b/projects/llm_framework/main_kws/SConstruct @@ -4,10 +4,10 @@ Import('env') with open(env['PROJECT_TOOL_S']) as f: exec(f.read()) -SRCS = Glob('src/*.c*') +SRCS = append_srcs_dir(ADir('src')) INCLUDE = [ADir('include'), ADir('.')] PRIVATE_INCLUDE = [] -REQUIREMENTS = ['pthread', 'dl', 'utilities', 'eventpp', 'StackFlow', 'single_header_libs'] +REQUIREMENTS = ['pthread', 'dl', 'utilities', 'ax_msp', 'eventpp', 'StackFlow', 'single_header_libs'] STATIC_LIB = [] DYNAMIC_LIB = [] DEFINITIONS = [] @@ -22,7 +22,8 @@ DEFINITIONS += ['-std=c++17'] LDFLAGS+=['-Wl,-rpath=/opt/m5stack/lib', '-Wl,-rpath=/usr/local/m5stack/lib', '-Wl,-rpath=/usr/local/m5stack/lib/gcc-10.3', '-Wl,-rpath=/opt/lib', '-Wl,-rpath=/opt/usr/lib', '-Wl,-rpath=./'] LINK_SEARCH_PATH += [ADir('../static_lib')] -INCLUDE += [ADir('../static_lib/include/sherpa'), +INCLUDE += [ADir('src/runner'), + ADir('../static_lib/include/sherpa'), ADir('../static_lib/include/sherpa/fbank'), ADir('../static_lib/include/sherpa/sherpa-onnx'), ADir('../static_lib/include/sherpa/sherpa-onnx/onnxruntime-src'), @@ -30,6 +31,7 @@ INCLUDE += [ADir('../static_lib/include/sherpa'), ] LINK_SEARCH_PATH += [ADir('../static_lib/sherpa/onnx')] +REQUIREMENTS += ['ax_engine', 'ax_interpreter', 'ax_sys'] REQUIREMENTS += ['onnxruntime'] LDFLAGS += ['-l:libsherpa-onnx-core.a', '-l:libkaldi-native-fbank-core.a','-l:libkissfft-float.a', diff --git a/projects/llm_framework/main_kws/src/main.cpp b/projects/llm_framework/main_kws/src/main.cpp index 51022a8..8e70be5 100644 --- a/projects/llm_framework/main_kws/src/main.cpp +++ b/projects/llm_framework/main_kws/src/main.cpp @@ -5,6 +5,9 @@ */ #include "StackFlow.h" +#include "EngineWrapper.hpp" +#include "ax_sys_api.h" + #include #include #include @@ -34,9 +37,6 @@ static std::string base_model_config_path_; typedef std::function task_callback_t; #include "sherpa-onnx/csrc/keyword-spotter.h" -#include "sherpa-onnx/csrc/parse-options.h" - -#include #include "kaldi-native-fbank/csrc/online-feature.h" typedef struct mode_config_onnx { @@ -61,6 +61,7 @@ private: bool enstream_ = false; bool enwake_audio_ = true; std::atomic_bool audio_flage_; + static int ax_init_flage_; task_callback_t out_callback_; buffer_t *pcmdata; std::string wake_wav_file_; @@ -72,8 +73,8 @@ private: std::unique_ptr sherpa_stream_; kws_config_onnx onnx_config_; - std::vector onnx_cache_; - std::unique_ptr onnx_session_; + std::vector axera_cache_; + std::unique_ptr axera_session_; knf::FbankOptions fbank_opts_; std::unique_ptr fbank_; Ort::Env onnx_env_{ORT_LOGGING_LEVEL_WARNING, "kws"}; @@ -328,16 +329,20 @@ public: } std::string base_model = base_model_path_ + model_ + "/"; SLOGI("base_model %s", base_model.c_str()); - std::string model_file = base_model + "kws.onnx"; + std::string model_file = base_model + "kws.axmodel"; if (config_body.contains("wake_wav_file")) wake_wav_file_ = config_body["wake_wav_file"]; else if (file_body["mode_param"].contains("wake_wav_file")) wake_wav_file_ = file_body["mode_param"]["wake_wav_file"]; - onnx_session_ = std::make_unique(onnx_env_, model_file.c_str(), session_options_); + axera_session_ = std::make_unique(); + if (0 != axera_session_->Init(model_file.c_str())) { + SLOGE("Init axera model failed!"); + return -5; + } - onnx_cache_.assign(1 * 32 * 88, 0.0f); + axera_cache_.assign(1 * 32 * 88, 0.0f); auto &mp = file_body["mode_param"]; CONFIG_AUTO_SET_ONNX(mp, chunk_size); @@ -414,37 +419,46 @@ public: std::vector run_inference(const std::vector &audio_chunk_16k) { - std::vector> fbank_feats; - fbank_feats = compute_fbank_kaldi(audio_chunk_16k, onnx_config_.RESAMPLE_RATE, onnx_config_.FEAT_DIM); - if (fbank_feats.empty()) { + std::vector> fbank_feats = + compute_fbank_kaldi(audio_chunk_16k, onnx_config_.RESAMPLE_RATE, onnx_config_.FEAT_DIM); + if (fbank_feats.empty()) return {}; + + constexpr int FIX_T = 32; + const int FEAT_DIM = onnx_config_.FEAT_DIM; + + std::vector mat_flattened; + mat_flattened.resize(FIX_T * FEAT_DIM, 0.0f); + + const int T_in = static_cast(fbank_feats.size()); + const int T_copy = std::min(T_in, FIX_T); + + for (int t = 0; t < T_copy; ++t) { + if ((int)fbank_feats[t].size() < FEAT_DIM) continue; + std::memcpy(mat_flattened.data() + t * FEAT_DIM, fbank_feats[t].data(), sizeof(float) * FEAT_DIM); + } + + axera_session_->SetInput(mat_flattened.data(), 0); + + axera_session_->SetInput(axera_cache_.data(), 1); + + int ret = axera_session_->Run(); + if (ret) { + SLOGE("axera_session run failed!"); return {}; } - int T = fbank_feats.size(); - std::vector mat_flattened; - for (const auto &feat : fbank_feats) { - mat_flattened.insert(mat_flattened.end(), feat.begin(), feat.end()); + + const float *out_ptr = reinterpret_cast(axera_session_->GetOutputPtr(0)); + size_t out_size_f = axera_session_->GetOutputSize(0) / sizeof(float); + std::vector out_chunk(out_ptr, out_ptr + out_size_f); + + const float *cache_ptr = reinterpret_cast(axera_session_->GetOutputPtr(1)); + size_t cache_size_f = axera_session_->GetOutputSize(1) / sizeof(float); + if (cache_size_f != axera_cache_.size()) { + SLOGE("cache size mismatch: out=%zu, local=%zu", cache_size_f, axera_cache_.size()); + return out_chunk; } - std::vector input_shape = {1, static_cast(T), onnx_config_.FEAT_DIM}; - std::vector cache_shape = {1, 32, 88}; - Ort::MemoryInfo memory_info = Ort::MemoryInfo::CreateCpu(OrtDeviceAllocator, OrtMemTypeDefault); - Ort::Value input_tensor = Ort::Value::CreateTensor( - memory_info, mat_flattened.data(), mat_flattened.size(), input_shape.data(), input_shape.size()); - Ort::Value cache_tensor = Ort::Value::CreateTensor(memory_info, onnx_cache_.data(), onnx_cache_.size(), - cache_shape.data(), cache_shape.size()); - const char *input_names[] = {"input", "cache"}; - const char *output_names[] = {"output", "r_cache"}; - std::vector inputs; - inputs.push_back(std::move(input_tensor)); - inputs.push_back(std::move(cache_tensor)); - auto output_tensors = - onnx_session_->Run(Ort::RunOptions{nullptr}, input_names, inputs.data(), 2, output_names, 2); - float *out_data = output_tensors[0].GetTensorMutableData(); - float *cache_out_data = output_tensors[1].GetTensorMutableData(); - std::vector out_shape = output_tensors[0].GetTensorTypeAndShapeInfo().GetShape(); - size_t out_size = 1; - for (auto dim : out_shape) out_size *= dim; - std::vector out_chunk(out_data, out_data + out_size); - std::copy(cache_out_data, cache_out_data + onnx_cache_.size(), onnx_cache_.begin()); + std::memcpy(axera_cache_.data(), cache_ptr, axera_cache_.size() * sizeof(float)); + return out_chunk; } @@ -531,16 +545,45 @@ public: bool delete_model() { - sherpa_spotter_.reset(); - sherpa_stream_.reset(); - onnx_session_.reset(); - fbank_.reset(); + if (sherpa_spotter_) sherpa_spotter_.reset(); + if (sherpa_stream_) sherpa_stream_.reset(); + if (axera_session_) axera_session_->Release(); + if (fbank_) fbank_.reset(); return true; } llm_task(const std::string &workid) : audio_flage_(false) { pcmdata = buffer_create(); + _ax_init(); + } + + void _ax_init() + { + if (!ax_init_flage_) { + int ret = AX_SYS_Init(); + if (0 != ret) { + fprintf(stderr, "AX_SYS_Init failed! ret = 0x%x\n", ret); + } + AX_ENGINE_NPU_ATTR_T npu_attr; + memset(&npu_attr, 0, sizeof(npu_attr)); + ret = AX_ENGINE_Init(&npu_attr); + if (0 != ret) { + fprintf(stderr, "Init ax-engine failed{0x%8x}.\n", ret); + } + } + ax_init_flage_++; + } + + void _ax_deinit() + { + if (ax_init_flage_ > 0) { + --ax_init_flage_; + if (!ax_init_flage_) { + AX_ENGINE_Deinit(); + AX_SYS_Deinit(); + } + } } void start() @@ -555,9 +598,13 @@ public: { stop(); buffer_destroy(pcmdata); + if (axera_session_) axera_session_->Release(); + _ax_deinit(); } }; +int llm_task::ax_init_flage_ = 0; + class llm_kws : public StackFlow { private: enum { EVENT_TRIGGER = EVENT_EXPORT + 1 }; diff --git a/projects/llm_framework/main_kws/src/runner/EngineWrapper.cpp b/projects/llm_framework/main_kws/src/runner/EngineWrapper.cpp new file mode 100644 index 0000000..2ba9ed6 --- /dev/null +++ b/projects/llm_framework/main_kws/src/runner/EngineWrapper.cpp @@ -0,0 +1,357 @@ +/************************************************************************************************** + * + * Copyright (c) 2019-2023 Axera Semiconductor (Ningbo) Co., Ltd. All Rights Reserved. + * + * This source file is the property of Axera Semiconductor (Ningbo) Co., Ltd. and + * may not be copied or distributed in any isomorphic form without the prior + * written consent of Axera Semiconductor (Ningbo) Co., Ltd. + * + **************************************************************************************************/ +#include "EngineWrapper.hpp" +#include "utils/io.hpp" + +#include +#include + +#if defined(CONFIG_AX_650C_MSP_ENABLED) +static const char *strAlgoModelType[AX_ENGINE_MODEL_TYPE_BUTT] = {"3.6T", "7.2T", "18T"}; +#endif + +#if defined(CONFIG_AX_620E_MSP_ENABLED) || defined(CONFIG_AX_620Q_MSP_ENABLED) +static const char *strAlgoModelType[AX_ENGINE_MODEL_TYPE_BUTT] = {"HalfOCM", "FullOCM"}; +#endif + +/// @brief npu type +typedef enum axNPU_TYPE_E { + AX_NPU_DEFAULT = 0, /* running under default NPU according to system */ + AX_STD_VNPU_1 = (1 << 0), /* running under STD VNPU1 */ + AX_STD_VNPU_2 = (1 << 1), /* running under STD VNPU2 */ + AX_STD_VNPU_3 = (1 << 2), /* running under STD VNPU3 */ + AX_BL_VNPU_1 = (1 << 3), /* running under BIG-LITTLE VNPU1 */ + AX_BL_VNPU_2 = (1 << 4) /* running under BIG-LITTLE VNPU2 */ +} AX_NPU_TYPE_E; + +#if defined(CONFIG_AX_650C_MSP_ENABLED) +static AX_S32 CheckModelVNpu(const std::string &strModel, const AX_ENGINE_MODEL_TYPE_T &eModelType, + const AX_S32 &nNpuType, AX_U32 &nNpuSet) +{ + AX_ENGINE_NPU_ATTR_T stNpuAttr; + memset(&stNpuAttr, 0x00, sizeof(stNpuAttr)); + + auto ret = AX_ENGINE_GetVNPUAttr(&stNpuAttr); + if (ret == 0) { + // VNPU DISABLE + if (stNpuAttr.eHardMode == AX_ENGINE_VIRTUAL_NPU_DISABLE) { + nNpuSet = 0x01; // NON-VNPU (0b111) + // printf("%s will run under VNPU-DISABLE [%s]\n", strModel.c_str(), strAlgoModelType[eModelType]); + } + // STD VNPU + else if (stNpuAttr.eHardMode == AX_ENGINE_VIRTUAL_NPU_STD) { + // 7.2T & 10.8T no allow + if (eModelType == AX_ENGINE_MODEL_TYPE1 || eModelType == AX_ENGINE_MODEL_TYPE2) { + // printf("%s model type%d: [%s], no allow run under STD VNPU\n", strModel.c_str(), eModelType, + // strAlgoModelType[eModelType]); + return -1; + } + + // default STD VNPU2 + if (nNpuType == 0) { + nNpuSet = 0x02; // VNPU2 (0b010) + // printf("%s will run under default STD-VNPU2 [%s]\n", strModel.c_str(), strAlgoModelType[eModelType]); + } else { + if (nNpuType & AX_STD_VNPU_1) { + nNpuSet |= 0x01; // VNPU1 (0b001) + // printf("%s will run under STD-VNPU1 [%s]\n", strModel.c_str(), strAlgoModelType[eModelType]); + } + if (nNpuType & AX_STD_VNPU_2) { + nNpuSet |= 0x02; // VNPU2 (0b010) + // printf("%s will run under STD-VNPU2 [%s]\n", strModel.c_str(), strAlgoModelType[eModelType]); + } + if (nNpuType & AX_STD_VNPU_3) { + nNpuSet |= 0x04; // VNPU3 (0b100) + // printf("%s will run under STD-VNPU3 [%s]\n", strModel.c_str(), strAlgoModelType[eModelType]); + } + } + } + // BL VNPU + else if (stNpuAttr.eHardMode == AX_ENGINE_VIRTUAL_NPU_BIG_LITTLE) { + // 10.8T no allow + if (eModelType == AX_ENGINE_MODEL_TYPE2) { + // printf("%s model type%d: [%s], no allow run under BL VNPU\n", strModel.c_str(), eModelType, + // strAlgoModelType[eModelType]); + return -1; + } + + // default BL VNPU + if (nNpuType == 0) { + // 7.2T default BL VNPU1 + if (eModelType == AX_ENGINE_MODEL_TYPE1) { + nNpuSet = 0x01; // VNPU1 (0b001) + // printf("%s will run under default BL-VNPU1 [%s]\n", strModel.c_str(), + // strAlgoModelType[eModelType]); + } + // 3.6T default BL VNPU2 + else { + nNpuSet = 0x02; // VNPU2 (0b010) + // printf("%s will run under default BL-VNPU2 [%s]\n", strModel.c_str(), + // strAlgoModelType[eModelType]); + } + } else { + // 7.2T + if (eModelType == AX_ENGINE_MODEL_TYPE1) { + // no allow set to BL VNPU2 + if (nNpuType & AX_BL_VNPU_2) { + // printf("%s model type%d: [%s], no allow run under BL VNPU2\n", strModel.c_str(), eModelType, + // strAlgoModelType[eModelType]); + return -1; + } + if (nNpuType & AX_BL_VNPU_1) { + nNpuSet |= 0x01; // VNPU1 (0b001) + // printf("%s will run under BL-VNPU1 [%s]\n", strModel.c_str(), strAlgoModelType[eModelType]); + } + } + // 3.6T + else { + if (nNpuType & AX_BL_VNPU_1) { + nNpuSet |= 0x01; // VNPU1 (0b001) + // printf("%s will run under BL-VNPU1 [%s]\n", strModel.c_str(), strAlgoModelType[eModelType]); + } + if (nNpuType & AX_BL_VNPU_2) { + nNpuSet |= 0x02; // VNPU2 (0b010) + // printf("%s will run under BL-VNPU2 [%s]\n", strModel.c_str(), strAlgoModelType[eModelType]); + } + } + } + } + } else { + printf("AX_ENGINE_GetVNPUAttr fail ret = %x\n", ret); + } + + return ret; +} +#endif + +#if defined(CONFIG_AX_620E_MSP_ENABLED) || defined(CONFIG_AX_620Q_MSP_ENABLED) +static AX_S32 CheckModelVNpu(const std::string &strModel, const AX_ENGINE_MODEL_TYPE_T &eModelType, + const AX_S32 &nNpuType, AX_U32 &nNpuSet) +{ + AX_ENGINE_NPU_ATTR_T stNpuAttr; + memset(&stNpuAttr, 0x00, sizeof(stNpuAttr)); + + auto ret = AX_ENGINE_GetVNPUAttr(&stNpuAttr); + if (ret == 0) { + // VNPU DISABLE + if (stNpuAttr.eHardMode == AX_ENGINE_VIRTUAL_NPU_DISABLE) { + nNpuSet = 0x01; // NON-VNPU (0b111) + // ALOGN("%s will run under VNPU-DISABLE [%s]", strModel.c_str(), strAlgoModelType[eModelType]); + } + // STD VNPU + else if (stNpuAttr.eHardMode == AX_ENGINE_VIRTUAL_NPU_ENABLE) { + // full ocm model was no allowned + if (eModelType == AX_ENGINE_MODEL_TYPE1) { + // printf("%s model type%d: [%s], no allow run under STD VNPU", strModel.c_str(), eModelType, + // strAlgoModelType[eModelType]); + return -1; + } + + // default STD VNPU2 + if (nNpuType == 0) { + nNpuSet = 0x02; // VNPU2 (0b010) + // printf("%s will run under default STD-VNPU2 [%s]", strModel.c_str(), strAlgoModelType[eModelType]); + } else { + if (nNpuType & AX_STD_VNPU_1) { + nNpuSet |= 0x01; // VNPU1 (0b001) + // printf("%s will run under STD-VNPU1 [%s]", strModel.c_str(), strAlgoModelType[eModelType]); + } + if (nNpuType & AX_STD_VNPU_2) { + nNpuSet |= 0x02; // VNPU2 (0b010) + // printf("%s will run under STD-VNPU2 [%s]", strModel.c_str(), strAlgoModelType[eModelType]); + } + } + } + } else { + printf("AX_ENGINE_GetVNPUAttr fail ret = %x", ret); + } + + return ret; +} +#endif + +int EngineWrapper::Init(const char *strModelPath, uint32_t nNpuType) +{ + AX_S32 ret = 0; + + // 1. load model + AX_BOOL bLoadModelUseCmm = AX_TRUE; + AX_CHAR *pModelBufferVirAddr = nullptr; + AX_U64 u64ModelBufferPhyAddr = 0; + AX_U32 nModelBufferSize = 0; + + std::vector model_buffer; + + if (bLoadModelUseCmm) { + if (!utils::read_file(strModelPath, (AX_VOID **)&pModelBufferVirAddr, u64ModelBufferPhyAddr, + nModelBufferSize)) { + printf("ALGO read model(%s) fail\n", strModelPath); + return -1; + } + } else { + if (!utils::read_file(strModelPath, model_buffer)) { + printf("ALGO read model(%s) fail\n", strModelPath); + return -1; + } + + pModelBufferVirAddr = model_buffer.data(); + nModelBufferSize = model_buffer.size(); + } + + auto freeModelBuffer = [&]() { + if (bLoadModelUseCmm) { + if (u64ModelBufferPhyAddr != 0) { + AX_SYS_MemFree(u64ModelBufferPhyAddr, &pModelBufferVirAddr); + } + } else { + std::vector().swap(model_buffer); + } + return; + }; + + // 1.1 Get Model Type + AX_ENGINE_MODEL_TYPE_T eModelType = AX_ENGINE_MODEL_TYPE0; + ret = AX_ENGINE_GetModelType(pModelBufferVirAddr, nModelBufferSize, &eModelType); + if (0 != ret || eModelType >= AX_ENGINE_MODEL_TYPE_BUTT) { + printf("%s AX_ENGINE_GetModelType fail ret=%x, eModelType=%d\n", strModelPath, eModelType); + freeModelBuffer(); + return -1; + } + + // 1.2 Check VNPU + AX_ENGINE_NPU_SET_T nNpuSet = 0; + ret = CheckModelVNpu(strModelPath, eModelType, nNpuType, nNpuSet); + if (0 != ret) { + printf("ALGO CheckModelVNpu fail\n"); + freeModelBuffer(); + return -1; + } + + // 2. create handle + AX_ENGINE_HANDLE handle = nullptr; + ret = AX_ENGINE_CreateHandle(&handle, pModelBufferVirAddr, nModelBufferSize); + auto deinit_handle = [&handle]() { + if (handle) { + AX_ENGINE_DestroyHandle(handle); + } + return -1; + }; + + freeModelBuffer(); + + if (0 != ret || !handle) { + printf("ALGO Create model(%s) handle fail\n", strModelPath); + + return deinit_handle(); + } + + // 3. create context + ret = AX_ENGINE_CreateContext(handle); + if (0 != ret) { + return deinit_handle(); + } + + // 4. set io + m_io_info = nullptr; + ret = AX_ENGINE_GetIOInfo(handle, &m_io_info); + if (0 != ret) { + return deinit_handle(); + } + m_input_num = m_io_info->nInputSize; + m_output_num = m_io_info->nOutputSize; + + // 4.1 query io + // AX_IMG_FORMAT_E eDtype; + // ret = utils::query_model_input_size(m_io_info, m_input_size, eDtype);//FIXME. + // if (0 != ret) { + // printf("model(%s) query model input size fail\n", strModelPath.c_str()); + // return deinit_handle(); + // } + + // if (!(eDtype == AX_FORMAT_YUV420_SEMIPLANAR || eDtype == AX_FORMAT_YUV420_SEMIPLANAR_VU || + // eDtype == AX_FORMAT_RGB888 || eDtype == AX_FORMAT_BGR888)) { + // printf("model(%s) data type is: 0x%02X, unsupport\n", strModelPath, eDtype); + // return deinit_handle(); + // } + + // 4.2 brief io +#ifdef __DEBUG__ + printf("brief_io_info\n"); + utils::brief_io_info(strModelPath, m_io_info); +#endif + + // 5. Config VNPU + // printf("model(%s) nNpuSet: 0x%08X\n", strModelPath.c_str(), nNpuSet); + // will do nothing for using create handle v2 api + + // 6. prepare io + // AX_U32 nIoDepth = (stCtx.vecOutputBufferFlag.size() == 0) ? 1 : stCtx.vecOutputBufferFlag.size(); + ret = utils::prepare_io(strModelPath, m_io_info, m_io, utils::IO_BUFFER_STRATEGY_DEFAULT); + if (0 != ret) { + printf("prepare io failed!\n"); + utils::free_io(m_io); + return deinit_handle(); + } + + m_handle = handle; + m_hasInit = true; + + return 0; +} + +int EngineWrapper::SetInput(void *pInput, int index) +{ + return utils::push_io_input(pInput, index, m_io); +} + +int EngineWrapper::Run() +{ + if (!m_hasInit) return -1; + + // 7.3 run & benchmark + auto ret = AX_ENGINE_RunSync(m_handle, &m_io); + if (0 != ret) { + printf("AX_ENGINE_RunSync failed. ret=0x%x\n", ret); + return ret; + } + + return 0; +} + +int EngineWrapper::GetOutput(void *pOutput, int index) +{ + return utils::push_io_output(pOutput, index, m_io); +} + +int EngineWrapper::GetInputSize(int index) +{ + return m_io.pInputs[index].nSize; +} + +int EngineWrapper::GetOutputSize(int index) +{ + return m_io.pOutputs[index].nSize; +} + +void *EngineWrapper::GetOutputPtr(int index) +{ + utils::cache_io_flush(&m_io.pOutputs[index]); + return m_io.pOutputs[index].pVirAddr; +} + +int EngineWrapper::Release() +{ + if (m_handle) { + utils::free_io(m_io); + AX_ENGINE_DestroyHandle(m_handle); + m_handle = nullptr; + } + return 0; +} diff --git a/projects/llm_framework/main_kws/src/runner/EngineWrapper.hpp b/projects/llm_framework/main_kws/src/runner/EngineWrapper.hpp new file mode 100644 index 0000000..eecc80e --- /dev/null +++ b/projects/llm_framework/main_kws/src/runner/EngineWrapper.hpp @@ -0,0 +1,53 @@ +/************************************************************************************************** + * + * Copyright (c) 2019-2023 Axera Semiconductor (Ningbo) Co., Ltd. All Rights Reserved. + * + * This source file is the property of Axera Semiconductor (Ningbo) Co., Ltd. and + * may not be copied or distributed in any isomorphic form without the prior + * written consent of Axera Semiconductor (Ningbo) Co., Ltd. + * + **************************************************************************************************/ + +#pragma once + +#include +#include +#include +#include +#include + +#include "ax_engine_api.h" + +class EngineWrapper { +public: + EngineWrapper() : m_hasInit(false), m_handle(nullptr) + { + } + + ~EngineWrapper() + { + Release(); + } + + int Init(const char* strModelPath, uint32_t nNpuType = 0); + + int SetInput(void* pInput, int index); + + int Run(); + + int GetOutput(void* pOutput, int index); + + int GetInputSize(int index); + int GetOutputSize(int index); + + void* GetOutputPtr(int index); + + int Release(); + +protected: + bool m_hasInit; + AX_ENGINE_HANDLE m_handle; + AX_ENGINE_IO_INFO_T* m_io_info{}; + AX_ENGINE_IO_T m_io{}; + int m_input_num{}, m_output_num{}; +}; \ No newline at end of file diff --git a/projects/llm_framework/main_kws/src/runner/utils/checker.h b/projects/llm_framework/main_kws/src/runner/utils/checker.h new file mode 100644 index 0000000..e71a227 --- /dev/null +++ b/projects/llm_framework/main_kws/src/runner/utils/checker.h @@ -0,0 +1,32 @@ +/************************************************************************************************** + * + * Copyright (c) 2019-2023 Axera Semiconductor (Ningbo) Co., Ltd. All Rights Reserved. + * + * This source file is the property of Axera Semiconductor (Ningbo) Co., Ltd. and + * may not be copied or distributed in any isomorphic form without the prior + * written consent of Axera Semiconductor (Ningbo) Co., Ltd. + * + **************************************************************************************************/ + +#ifndef AX_CHECKER_H +#define AX_CHECKER_H + +#include "utils/logger.h" + +#define CHECK_PTR(p) \ + do { \ + if (!p) { \ + ALOGE("%s nil pointer\n", #p); \ + return -1; \ + } \ + } while (0) + +#define CHECK_INITED(p) \ + do { \ + if (!p->HasInit()) { \ + ALOGE("%s has not init\n", #p); \ + return -1; \ + } \ + } while (0) + +#endif // AX_CHECKER_H diff --git a/projects/llm_framework/main_kws/src/runner/utils/io.hpp b/projects/llm_framework/main_kws/src/runner/utils/io.hpp new file mode 100644 index 0000000..4c79f8f --- /dev/null +++ b/projects/llm_framework/main_kws/src/runner/utils/io.hpp @@ -0,0 +1,606 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * License); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * AS IS BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "utils/checker.h" +#include "ax_sys_api.h" +#include "ax_engine_type.h" + +#define IO_CMM_ALIGN_SIZE 128 + +namespace utils { +typedef enum { IO_BUFFER_STRATEGY_DEFAULT, IO_BUFFER_STRATEGY_CACHED } IO_BUFFER_STRATEGY_T; + +static inline AX_S32 query_model_input_size(const AX_ENGINE_IO_INFO_T* io_info, std::array& input_size, + AX_IMG_FORMAT_E& eDtype) +{ + int height = 0; + int width = 0; + int size = 0; + int channel = 0; + int data_type_size = 0; + auto& input = io_info->pInputs[0]; + + switch (input.eLayout) { + case AX_ENGINE_TENSOR_LAYOUT_NHWC: + height = input.pShape[1]; + width = input.pShape[2]; + channel = input.pShape[3]; + size = input.nSize; + break; + case AX_ENGINE_TENSOR_LAYOUT_NCHW: + channel = input.pShape[1]; + height = input.pShape[2]; + width = input.pShape[3]; + size = input.nSize; + break; + default: // NHWC + height = input.pShape[1]; + width = input.pShape[2]; + channel = input.pShape[3]; + size = input.nSize; + break; + } + + switch (input.eDataType) { + case AX_ENGINE_DT_UINT8: + case AX_ENGINE_DT_SINT8: + data_type_size = 1; + break; + case AX_ENGINE_DT_UINT16: + case AX_ENGINE_DT_SINT16: + data_type_size = 2; + break; + case AX_ENGINE_DT_FLOAT32: + data_type_size = 4; + break; + case AX_ENGINE_DT_SINT32: + case AX_ENGINE_DT_UINT32: + data_type_size = 4; + break; + case AX_ENGINE_DT_FLOAT64: + data_type_size = 8; + break; + default: + data_type_size = 1; + break; + } + + if (channel == 0 || height == 0 || width == 0 || size == 0 || data_type_size == 0) { + return -1; + } + + if (input.pExtraMeta) { + switch (input.pExtraMeta->eColorSpace) { + case AX_ENGINE_CS_BGR: + input_size[0] = height; + input_size[1] = width; + eDtype = AX_FORMAT_BGR888; + break; + case AX_ENGINE_CS_RGB: + input_size[0] = height; + input_size[1] = width; + eDtype = AX_FORMAT_RGB888; + break; + case AX_ENGINE_CS_NV12: + input_size[0] = height * 2 / 3; + input_size[1] = width; + eDtype = AX_FORMAT_YUV420_SEMIPLANAR; + break; + case AX_ENGINE_CS_NV21: + input_size[0] = height * 2 / 3; + input_size[1] = width; + eDtype = AX_FORMAT_YUV420_SEMIPLANAR_VU; + break; + default: // AX_ENGINE_CS_NV12 + input_size[0] = height * 2 / 3; + input_size[1] = width; + eDtype = AX_FORMAT_YUV420_SEMIPLANAR; + break; + } + } else { + input_size[0] = height * 2 / 3; + input_size[1] = width; + eDtype = AX_FORMAT_YUV420_SEMIPLANAR; + } + + ALOGD("eLayout:%d, eDataType:%d, channel:%d, height:%d, width:%d, size:%d, data_type_size:%d", input.eLayout, + input.eDataType, channel, input_size[0], input_size[1], size, data_type_size); + + return 0; +} + +static inline void brief_io_info(std::string strModel, const AX_ENGINE_IO_INFO_T* io_info) +{ + auto describe_shape_type = [](AX_ENGINE_TENSOR_LAYOUT_T type) -> const char* { + switch (type) { + case AX_ENGINE_TENSOR_LAYOUT_NHWC: + return "NHWC"; + case AX_ENGINE_TENSOR_LAYOUT_NCHW: + return "NCHW"; + default: + return "unknown"; + } + }; + auto describe_data_type = [](AX_ENGINE_DATA_TYPE_T type) -> const char* { + switch (type) { + case AX_ENGINE_DT_UINT8: + return "uint8"; + case AX_ENGINE_DT_UINT16: + return "uint16"; + case AX_ENGINE_DT_FLOAT32: + return "float32"; + case AX_ENGINE_DT_SINT16: + return "sint16"; + case AX_ENGINE_DT_SINT8: + return "sint8"; + case AX_ENGINE_DT_SINT32: + return "sint32"; + case AX_ENGINE_DT_UINT32: + return "uint32"; + case AX_ENGINE_DT_FLOAT64: + return "float64"; + case AX_ENGINE_DT_UINT10_PACKED: + return "uint10_packed"; + case AX_ENGINE_DT_UINT12_PACKED: + return "uint12_packed"; + case AX_ENGINE_DT_UINT14_PACKED: + return "uint14_packed"; + case AX_ENGINE_DT_UINT16_PACKED: + return "uint16_packed"; + default: + return "unknown"; + } + }; + auto describe_memory_type = [](AX_ENGINE_MEMORY_TYPE_T type) -> const char* { + switch (type) { + case AX_ENGINE_MT_PHYSICAL: + return "Physical"; + case AX_ENGINE_MT_VIRTUAL: + return "Virtual"; + default: + return "unknown"; + } + }; + auto describe_color_space = [](AX_ENGINE_COLOR_SPACE_T cs) -> const char* { + switch (cs) { + case AX_ENGINE_CS_FEATUREMAP: + return "FeatureMap"; + case AX_ENGINE_CS_BGR: + return "BGR"; + case AX_ENGINE_CS_RGB: + return "RGB"; + case AX_ENGINE_CS_RGBA: + return "RGBA"; + case AX_ENGINE_CS_GRAY: + return "GRAY"; + case AX_ENGINE_CS_NV12: + return "NV12"; + case AX_ENGINE_CS_NV21: + return "NV21"; + case AX_ENGINE_CS_YUV444: + return "YUV444"; + case AX_ENGINE_CS_RAW8: + return "RAW8"; + case AX_ENGINE_CS_RAW10: + return "RAW10"; + case AX_ENGINE_CS_RAW12: + return "RAW12"; + case AX_ENGINE_CS_RAW14: + return "RAW14"; + case AX_ENGINE_CS_RAW16: + return "RAW16"; + default: + return "unknown"; + } + }; + printf("Model Name: %s\n", strModel.c_str()); + printf("Max Batch Size %d\n", io_info->nMaxBatchSize); + printf("Support Dynamic Batch? %s\n", io_info->bDynamicBatchSize == AX_TRUE ? "Yes" : "No"); + + for (uint32_t i = 0; i < io_info->nInputSize; ++i) { + auto& input = io_info->pInputs[i]; + printf("Input[%d]: %s\n", i, input.pName); + printf(" Shape ["); + for (uint32_t j = 0; j < input.nShapeSize; ++j) { + printf("%d", (int)input.pShape[j]); + if (j + 1 < input.nShapeSize) printf(", "); + } + printf("] %s %s %s %s\n", describe_shape_type(input.eLayout), describe_data_type(input.eDataType), + input.pExtraMeta ? describe_color_space(input.pExtraMeta->eColorSpace) : "", + input.nQuantizationValue > 0 ? ("Q=" + std::to_string(input.nQuantizationValue)).c_str() : ""); + printf(" Memory %s\n", describe_memory_type(input.eMemoryType)); + printf(" Size %u\n", input.nSize); + } + for (uint32_t i = 0; i < io_info->nOutputSize; ++i) { + auto& output = io_info->pOutputs[i]; + printf("Output[%d]: %s\n", i, output.pName); + printf(" Shape ["); + for (uint32_t j = 0; j < output.nShapeSize; ++j) { + printf("%d", (int)output.pShape[j]); + if (j + 1 < output.nShapeSize) printf(", "); + } + printf("] %s %s %s\n", describe_shape_type(output.eLayout), describe_data_type(output.eDataType), + output.nQuantizationValue > 0 ? ("Q=" + std::to_string(output.nQuantizationValue)).c_str() : ""); + printf(" Memory %s\n", describe_memory_type(output.eMemoryType)); + printf(" Size %u\n", output.nSize); + } +} + +static inline AX_S32 alloc_engine_buffer(const std::string& token, const std::string& appendix, size_t index, + const AX_ENGINE_IOMETA_T* pMeta, AX_ENGINE_IO_BUFFER_T* pBuf, + IO_BUFFER_STRATEGY_T eStrategy = IO_BUFFER_STRATEGY_DEFAULT) +{ + AX_S32 ret = -1; + if (eStrategy != IO_BUFFER_STRATEGY_DEFAULT && eStrategy != IO_BUFFER_STRATEGY_CACHED) { + fprintf(stderr, "strategy %d not supported\n", (int)eStrategy); + return -1; + } + memset(pBuf, 0, sizeof(AX_ENGINE_IO_BUFFER_T)); + pBuf->nSize = pMeta->nSize; + + const std::string token_name = "skel_" + token + appendix + std::to_string(index); + + if (eStrategy == IO_BUFFER_STRATEGY_CACHED) { + ret = AX_SYS_MemAllocCached((AX_U64*)&pBuf->phyAddr, &pBuf->pVirAddr, pBuf->nSize, IO_CMM_ALIGN_SIZE, + (const AX_S8*)token_name.c_str()); + } else { + ret = AX_SYS_MemAlloc((AX_U64*)&pBuf->phyAddr, &pBuf->pVirAddr, pBuf->nSize, IO_CMM_ALIGN_SIZE, + (const AX_S8*)token_name.c_str()); + } + + return ret; +} + +static inline AX_S32 free_engine_buffer(AX_ENGINE_IO_BUFFER_T* pBuf) +{ + if (pBuf->phyAddr == 0) { + delete[] reinterpret_cast(pBuf->pVirAddr); + } else { + AX_SYS_MemFree(pBuf->phyAddr, pBuf->pVirAddr); + } + pBuf->phyAddr = 0; + pBuf->pVirAddr = nullptr; + + return 0; +} + +static inline void free_io_index(AX_ENGINE_IO_BUFFER_T* io_buf, size_t index) +{ + AX_ENGINE_IO_BUFFER_T* pBuf = io_buf + index; + free_engine_buffer(pBuf); +} + +static inline void free_io(AX_ENGINE_IO_T& io) +{ + for (size_t j = 0; j < io.nInputSize; ++j) { + AX_ENGINE_IO_BUFFER_T* pBuf = io.pInputs + j; + AX_SYS_MemFree(pBuf->phyAddr, pBuf->pVirAddr); + } + for (size_t j = 0; j < io.nOutputSize; ++j) { + AX_ENGINE_IO_BUFFER_T* pBuf = io.pOutputs + j; + AX_SYS_MemFree(pBuf->phyAddr, pBuf->pVirAddr); + } + delete[] io.pInputs; + delete[] io.pOutputs; +} + +static inline void free_io(AX_ENGINE_IO_T& io, std::vector>& vecOutputBuffer) +{ + if (io.pInputs) { + delete[] io.pInputs; + io.pInputs = nullptr; + } + + if (io.pOutputs) { + for (size_t index = 0; index < vecOutputBuffer.size(); ++index) { + AX_ENGINE_IO_BUFFER_T* pOutputs = &vecOutputBuffer[index][0]; + for (size_t j = 0; j < io.nOutputSize; ++j) { + free_io_index(pOutputs, j); + } + } + + delete[] io.pOutputs; + io.pOutputs = nullptr; + } +} + +static inline int prepare_io(const std::string& token, const AX_ENGINE_IO_INFO_T* info, AX_ENGINE_IO_T& io, + IO_BUFFER_STRATEGY_T strategy) +{ + auto ret = 0; + + memset(&io, 0, sizeof(io)); + + io.pInputs = new AX_ENGINE_IO_BUFFER_T[info->nInputSize]; + + if (!io.pInputs) { + goto EXIT; + } + + memset(io.pInputs, 0x00, sizeof(AX_ENGINE_IO_BUFFER_T) * info->nInputSize); + io.nInputSize = info->nInputSize; + for (AX_U32 i = 0; i < info->nInputSize; ++i) { + auto meta = info->pInputs[i]; + auto buffer = &io.pInputs[i]; + ret = alloc_engine_buffer(token, "_input_", i, &meta, buffer, strategy); + if (ret != 0) { + free_io_index(io.pInputs, i); + return ret; + } + } + + io.pOutputs = new AX_ENGINE_IO_BUFFER_T[info->nOutputSize]; + + if (!io.pOutputs) { + goto EXIT; + } + + memset(io.pOutputs, 0x00, sizeof(AX_ENGINE_IO_BUFFER_T) * info->nOutputSize); + io.nOutputSize = info->nOutputSize; + + for (size_t i = 0; i < info->nOutputSize; ++i) { + auto meta = info->pOutputs[i]; + auto buffer = &io.pOutputs[i]; + ret = alloc_engine_buffer(token, "_output_", i, &meta, buffer, strategy); + if (ret != 0) { + goto EXIT; + } + } + +EXIT: + if (ret != 0) { + free_io(io); + return -1; + } + + return 0; +} + +static inline int prepare_io(const std::string& token, const AX_ENGINE_IO_INFO_T* info, AX_ENGINE_IO_T& io, + std::vector& vecOutputBuffer, const IO_BUFFER_STRATEGY_T& strategy) +{ + AX_S32 ret = 0; + memset(&io, 0, sizeof(io)); + + std::vector outputBuffer; + + if (1 != info->nInputSize) { + fprintf(stderr, "[ERR]: Only single input was accepted(got %u).\n", info->nInputSize); + return -1; + } + + io.pInputs = new AX_ENGINE_IO_BUFFER_T[info->nInputSize]; + + if (!io.pInputs) { + goto EXIT; + } + + memset(io.pInputs, 0x00, sizeof(AX_ENGINE_IO_BUFFER_T) * info->nInputSize); + io.nInputSize = info->nInputSize; + + for (AX_U32 i = 0; i < info->nInputSize; ++i) { + auto meta = info->pInputs[i]; + auto buffer = &io.pInputs[i]; + ret = alloc_engine_buffer(token, "_input_", i, &meta, buffer, strategy); + if (ret != 0) { + free_io_index(io.pInputs, i); + return ret; + } + } + + io.pOutputs = new AX_ENGINE_IO_BUFFER_T[info->nOutputSize]; + + if (!io.pOutputs) { + goto EXIT; + } + + for (size_t i = 0; i < info->nOutputSize; ++i) { + auto meta = info->pOutputs[i]; + auto buffer = &io.pOutputs[i]; + ret = alloc_engine_buffer(token, "_output_", i, &meta, buffer, strategy); + + if (ret != 0) { + goto EXIT; + } + + vecOutputBuffer.push_back(*buffer); + } + + memset(io.pOutputs, 0x00, sizeof(AX_ENGINE_IO_BUFFER_T) * info->nOutputSize); + io.nOutputSize = info->nOutputSize; + + for (size_t i = 0; i < info->nOutputSize; ++i) { + auto buffer = &io.pOutputs[i]; + *buffer = vecOutputBuffer[i]; + } + +EXIT: + if (ret != 0) { + free_io(io); + return -1; + } + + return 0; +} + +static inline AX_S32 push_io_output(const AX_ENGINE_IO_INFO_T* info, AX_ENGINE_IO_T& io, + std::vector& outputBuffer) +{ + for (size_t i = 0; i < info->nOutputSize; ++i) { + auto buffer = &io.pOutputs[i]; + *buffer = outputBuffer[i]; + } + + return 0; +} + +static inline AX_S32 cache_io_flush(const AX_ENGINE_IO_BUFFER_T* io_buf) +{ + if (io_buf->phyAddr != 0) { + AX_SYS_MflushCache(io_buf->phyAddr, io_buf->pVirAddr, io_buf->nSize); + } + + return 0; +} + +static inline AX_S32 push_io_input(void* input, int index, AX_ENGINE_IO_T& io) +{ + // img ranks_depth ranks_feat ranks_bev, n_points + AX_ENGINE_IO_BUFFER_T* pImg = &io.pInputs[index]; + + memcpy(pImg->pVirAddr, input, pImg->nSize); + cache_io_flush(pImg); + return 0; +} + +static inline AX_S32 push_io_output(void* output, int index, AX_ENGINE_IO_T& io) +{ + AX_ENGINE_IO_BUFFER_T* pImg = &io.pOutputs[index]; + cache_io_flush(pImg); + memcpy(output, pImg->pVirAddr, pImg->nSize); + return 0; +} + +static inline AX_S32 cpu_copy(AX_U64 nPhyAddrSrc, AX_U64 nPhyAddrDst, AX_U32 nLen) +{ + if (nPhyAddrSrc != 0 && nPhyAddrDst != 0 && nLen > 0) { + AX_VOID* pSrcVirAddr = AX_SYS_MmapCache(nPhyAddrSrc, nLen); + AX_VOID* pDstVirAddr = AX_SYS_MmapCache(nPhyAddrDst, nLen); + + memcpy((AX_VOID*)pDstVirAddr, (AX_VOID*)pSrcVirAddr, nLen); + + AX_SYS_Munmap(pSrcVirAddr, nLen); + AX_SYS_Munmap(pDstVirAddr, nLen); + + return 0; + } + + return -1; +} + +static inline AX_S32 inc_io_ref_cnt(const AX_VIDEO_FRAME_T& stFrame) +{ + if (stFrame.u32BlkId[0] > 0) { + AX_POOL_IncreaseRefCnt(stFrame.u32BlkId[0]); + } + if (stFrame.u32BlkId[1] > 0) { + AX_POOL_IncreaseRefCnt(stFrame.u32BlkId[1]); + } + if (stFrame.u32BlkId[2] > 0) { + AX_POOL_IncreaseRefCnt(stFrame.u32BlkId[2]); + } + + return 0; +} + +static inline AX_S32 dec_io_ref_cnt(const AX_VIDEO_FRAME_T& stFrame) +{ + if (stFrame.u32BlkId[0] > 0) { + AX_POOL_DecreaseRefCnt(stFrame.u32BlkId[0]); + } + if (stFrame.u32BlkId[1] > 0) { + AX_POOL_DecreaseRefCnt(stFrame.u32BlkId[1]); + } + if (stFrame.u32BlkId[2] > 0) { + AX_POOL_DecreaseRefCnt(stFrame.u32BlkId[2]); + } + + return 0; +} + +static inline bool read_file(const char* path, std::vector& data) +{ + std::fstream fs(path, std::ios::in | std::ios::binary); + + if (!fs.is_open()) { + return false; + } + + fs.seekg(std::ios::end); + auto fs_end = fs.tellg(); + fs.seekg(std::ios::beg); + auto fs_beg = fs.tellg(); + + auto file_size = static_cast(fs_end - fs_beg); + auto vector_size = data.size(); + + data.reserve(vector_size + file_size); + data.insert(data.end(), std::istreambuf_iterator(fs), std::istreambuf_iterator()); + + fs.close(); + + return true; +} + +static inline bool read_file(const char* path, AX_VOID** pModelBufferVirAddr, AX_U64& u64ModelBufferPhyAddr, + AX_U32& nModelBufferSize) +{ + std::fstream fs(path, std::ios::in | std::ios::binary); + + if (!fs.is_open()) { + return false; + } + + fs.seekg(0, std::ios::end); + int file_size = fs.tellg(); + fs.seekg(0, std::ios::beg); + + nModelBufferSize = (AX_U32)file_size; + + AX_SYS_MemAlloc(&u64ModelBufferPhyAddr, pModelBufferVirAddr, nModelBufferSize, 0x100, (AX_S8*)"SKEL-CV"); + + if (!pModelBufferVirAddr || (u64ModelBufferPhyAddr == 0)) { + return false; + } + + fs.read((AX_CHAR*)*pModelBufferVirAddr, nModelBufferSize); + + fs.close(); + + return true; +} + +static inline void dequant(float** pptrOutput, const AX_ENGINE_IOMETA_T& ptrIoInfo, const AX_ENGINE_IO_BUFFER_T& ioBuf, + float zp, float scale) +{ + if (ptrIoInfo.eDataType == AX_ENGINE_DT_FLOAT32) { + *pptrOutput = (float*)ioBuf.pVirAddr; + return; + } + + *pptrOutput = (float*)malloc(ptrIoInfo.nSize * sizeof(float)); + uint8_t* pBuf = (uint8_t*)ioBuf.pVirAddr; + float* pOutput = *pptrOutput; + // float inv_scale = 1.0f / scale; + for (int i = 0; i < ptrIoInfo.nSize; i++) { + pOutput[i] = ((float)pBuf[i] - zp) * scale; + } +} +} // namespace utils diff --git a/projects/llm_framework/main_kws/src/runner/utils/logger.h b/projects/llm_framework/main_kws/src/runner/utils/logger.h new file mode 100644 index 0000000..81969e2 --- /dev/null +++ b/projects/llm_framework/main_kws/src/runner/utils/logger.h @@ -0,0 +1,84 @@ +/************************************************************************************************** + * + * Copyright (c) 2019-2023 Axera Semiconductor (Ningbo) Co., Ltd. All Rights Reserved. + * + * This source file is the property of Axera Semiconductor (Ningbo) Co., Ltd. and + * may not be copied or distributed in any isomorphic form without the prior + * written consent of Axera Semiconductor (Ningbo) Co., Ltd. + * + **************************************************************************************************/ + +#ifndef SKEL_LOGGER_H +#define SKEL_LOGGER_H + +#include "ax_global_type.h" +#include "ax_sys_log.h" + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +// #define SKEL_LOG_TAG "SKEL" +// +// #define ALOGE(fmt, ...) AX_LOG_ERR_EX(SKEL_LOG_TAG, AX_ID_SKEL, fmt, ##__VA_ARGS__) +// #define ALOGW(fmt, ...) AX_LOG_WARN_EX(SKEL_LOG_TAG, AX_ID_SKEL, fmt, ##__VA_ARGS__) +// #define ALOGI(fmt, ...) AX_LOG_INFO_EX(SKEL_LOG_TAG, AX_ID_SKEL, fmt, ##__VA_ARGS__) +// #define ALOGD(fmt, ...) AX_LOG_DBG_EX(SKEL_LOG_TAG, AX_ID_SKEL, fmt, ##__VA_ARGS__) +// #define ALOGN(fmt, ...) AX_LOG_NOTICE_EX(SKEL_LOG_TAG, AX_ID_SKEL, fmt, ##__VA_ARGS__) + +typedef enum { + SKEL_LOG_MIN = -1, + SKEL_LOG_EMERGENCY = 0, + SKEL_LOG_ALERT = 1, + SKEL_LOG_CRITICAL = 2, + SKEL_LOG_ERROR = 3, + SKEL_LOG_WARN = 4, + SKEL_LOG_NOTICE = 5, + SKEL_LOG_INFO = 6, + SKEL_LOG_DEBUG = 7, + SKEL_LOG_MAX +} SKEL_LOG_LEVEL_E; + +static SKEL_LOG_LEVEL_E log_level = SKEL_LOG_DEBUG; + +#if 1 +#define MACRO_BLACK "\033[1;30;30m" +#define MACRO_RED "\033[1;30;31m" +#define MACRO_GREEN "\033[1;30;32m" +#define MACRO_YELLOW "\033[1;30;33m" +#define MACRO_BLUE "\033[1;30;34m" +#define MACRO_PURPLE "\033[1;30;35m" +#define MACRO_WHITE "\033[1;30;37m" +#define MACRO_END "\033[0m" +#else +#define MACRO_BLACK +#define MACRO_RED +#define MACRO_GREEN +#define MACRO_YELLOW +#define MACRO_BLUE +#define MACRO_PURPLE +#define MACRO_WHITE +#define MACRO_END +#endif + +#define ALOGE(fmt, ...) printf(MACRO_RED "[E][%32s][%4d]: " fmt MACRO_END "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__) +#define ALOGW(fmt, ...) \ + if (log_level >= SKEL_LOG_WARN) \ + printf(MACRO_YELLOW "[W][%32s][%4d]: " fmt MACRO_END "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__) +#define ALOGI(fmt, ...) \ + if (log_level >= SKEL_LOG_INFO) \ + printf(MACRO_GREEN "[I][%32s][%4d]: " fmt MACRO_END "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__) +#define ALOGD(fmt, ...) \ + if (log_level >= SKEL_LOG_DEBUG) \ + printf(MACRO_WHITE "[D][%32s][%4d]: " fmt MACRO_END "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__) +#define ALOGN(fmt, ...) \ + if (log_level >= SKEL_LOG_NOTICE) \ + printf(MACRO_PURPLE "[N][%32s][%4d]: " fmt MACRO_END "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__) + +#ifdef __cplusplus +} +#endif + +#endif // SKEL_LOGGER_H