You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tvm.apache.org by GitBox <gi...@apache.org> on 2021/07/04 16:27:39 UTC
[GitHub] [tvm] areusch commented on a change in pull request #7742: Contributing the STM32 port
areusch commented on a change in pull request #7742:
URL: https://github.com/apache/tvm/pull/7742#discussion_r663522121
##########
File path: src/runtime/crt/contrib/stm32/ai_platform.h
##########
@@ -0,0 +1,383 @@
+/*
+ * 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.
+ */
+
+/*!
+ * \file ai_platform.h
+ * \brief Definitions of AI platform public APIs types
+ */
+
+// LINT_C_FILE
+
+#ifndef AI_PLATFORM_H
+#define AI_PLATFORM_H
+#pragma once
+
+#include <inttypes.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#ifndef AI_PLATFORM_API_MAJOR
+#define AI_PLATFORM_API_MAJOR (0)
+#endif
+#ifndef AI_PLATFORM_API_MINOR
+#define AI_PLATFORM_API_MINOR (6)
+#endif
+#ifndef AI_PLATFORM_API_MICRO
+#define AI_PLATFORM_API_MICRO (0)
+#endif
+
+#define AI_PLATFORM_API_VERSION \
+ AI_VERSION(AI_PLATFORM_API_MAJOR, AI_PLATFORM_API_MINOR, AI_PLATFORM_API_MICRO)
+
+#ifndef AI_TOOLS_API_VERSION_MAJOR
+#define AI_TOOLS_API_VERSION_MAJOR (1)
+#endif
+#ifndef AI_TOOLS_API_VERSION_MINOR
+#define AI_TOOLS_API_VERSION_MINOR (4)
+#endif
+#ifndef AI_TOOLS_API_VERSION_MICRO
+#define AI_TOOLS_API_VERSION_MICRO (0)
+#endif
+
+#define AI_TOOLS_API_VERSION \
+ AI_VERSION(AI_TOOLS_API_VERSION_MAJOR, AI_TOOLS_API_VERSION_MINOR, AI_TOOLS_API_VERSION_MICRO)
+
+#define AI_TOOLS_API_VERSION_1_3 AI_VERSION(1, 3, 0)
+
+/******************************************************************************/
+#ifdef __cplusplus
+#define AI_API_DECLARE_BEGIN extern "C" {
+#define AI_API_DECLARE_END }
+#else
+#include <stdbool.h>
+#define AI_API_DECLARE_BEGIN /* AI_API_DECLARE_BEGIN */
+#define AI_API_DECLARE_END /* AI_API_DECLARE_END */
+#endif
+
+/******************************************************************************/
+#if defined(_MSC_VER)
+#define AI_API_ENTRY __declspec(dllexport)
+#define AI_ALIGNED(x) /* AI_ALIGNED(x) */
+#elif defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
+#define AI_API_ENTRY /* AI_API_ENTRY */
+#define AI_ALIGNED(x) AI_CONCAT(AI_ALIGNED_, x)
+#define AI_ALIGNED_1 _Pragma("data_alignment = 1")
+#define AI_ALIGNED_2 _Pragma("data_alignment = 2")
+#define AI_ALIGNED_4 _Pragma("data_alignment = 4")
+#define AI_ALIGNED_8 _Pragma("data_alignment = 8")
+#define AI_ALIGNED_16 _Pragma("data_alignment = 16")
+#define AI_ALIGNED_32 _Pragma("data_alignment = 32")
+#elif defined(__CC_ARM)
+#define AI_API_ENTRY __attribute__((visibility("default")))
+#define AI_ALIGNED(x) __attribute__((aligned(x)))
+/* Keil disallows anonymous union initialization by default */
+#pragma anon_unions
+#elif defined(__GNUC__)
+#define AI_API_ENTRY __attribute__((visibility("default")))
+#define AI_ALIGNED(x) __attribute__((aligned(x)))
+#else
+/* Dynamic libraries are not supported by the compiler */
+#define AI_API_ENTRY /* AI_API_ENTRY */
+#define AI_ALIGNED(x) /* AI_ALIGNED(x) */
+#endif
+
+#define AI_HANDLE_PTR(ptr_) ((ai_handle)(ptr_))
+#define AI_HANDLE_NULL AI_HANDLE_PTR(NULL)
+
+#define AI_HANDLE_FUNC_PTR(func) ((ai_handle_func)(func))
+
+#define AI_NETWORK_PARAMS_INIT(params_, activations_) \
+ { .params = params_, .activations = activations_ }
+
+/*! ai_intq_info struct handlers **********************************************/
+#define INTQ_CONST const
+// #define INTQ_CONST
+
+#define AI_INTQ_INFO_LIST(list_) ((list_)->info)
+
+#define AI_INTQ_INFO_LIST_FLAGS(list_) ((list_) ? (list_)->flags : 0)
+
+#define AI_INTQ_INFO_LIST_SIZE(list_) ((list_) ? (list_)->size : 0)
+
+#define AI_HAS_INTQ_INFO_LIST(list_) ((list_) ? (((list_)->info) && ((list_)->size > 0)) : false)
+
+#define AI_INTQ_INFO_LIST_SCALE(list_, type_, pos_) \
+ (((list_) && (list_)->info && ((pos_) < (list_)->size)) \
+ ? ((type_*)((list_)->info->scale))[(pos_)] \
+ : 0)
+
+#define AI_INTQ_INFO_LIST_ZEROPOINT(list_, type_, pos_) \
+ (((list_) && (list_)->info && ((pos_) < (list_)->size)) \
+ ? ((type_*)((list_)->info->zeropoint))[(pos_)] \
+ : 0)
+
+/*! ai_buffer format handlers *************************************************/
+
+/*!
+ * @enum buffer format definition
+ * @ingroup ai_platform
+ *
+ * 32 bit signed format list.
+ */
+typedef int32_t ai_buffer_format;
+
+/*! ai_buffer_meta flags ******************************************************/
+#define AI_BUFFER_META_HAS_INTQ_INFO (0x1U << 0)
+#define AI_BUFFER_META_FLAG_SCALE_FLOAT (0x1U << 0)
+#define AI_BUFFER_META_FLAG_ZEROPOINT_U8 (0x1U << 1)
+#define AI_BUFFER_META_FLAG_ZEROPOINT_S8 (0x1U << 2)
+
+/*! ai_buffer format variable flags *******************************************/
+#define AI_BUFFER_FMT_TYPE_NONE (0x0)
+#define AI_BUFFER_FMT_TYPE_FLOAT (0x1)
+#define AI_BUFFER_FMT_TYPE_Q (0x2)
+#define AI_BUFFER_FMT_TYPE_BOOL (0x3)
+
+#define AI_BUFFER_FMT_FLAG_CONST (0x1U << 30)
+#define AI_BUFFER_FMT_FLAG_STATIC (0x1U << 29)
+#define AI_BUFFER_FMT_FLAG_IS_IO (0x1U << 27)
+
+#define AI_BUFFER_FMT_PACK(value_, mask_, bits_) (((value_) & (mask_)) << (bits_))
+
+#define AI_BUFFER_FMT_UNPACK(fmt_, mask_, bits_) ((AI_BUFFER_FMT_OBJ(fmt_) >> (bits_)) & (mask_))
+
+#define AI_BUFFER_FMT_OBJ(fmt_) ((ai_buffer_format)(fmt_))
+
+#define AI_BUFFER_FMT_GET_FLOAT(fmt_) AI_BUFFER_FMT_UNPACK(fmt_, 0x1, 24)
+
+#define AI_BUFFER_FMT_GET_SIGN(fmt_) AI_BUFFER_FMT_UNPACK(fmt_, 0x1, 23)
+
+#define AI_BUFFER_FMT_GET_TYPE(fmt_) AI_BUFFER_FMT_UNPACK(fmt_, 0xF, 17)
+
+#define AI_BUFFER_FMT_GET_BITS(fmt_) AI_BUFFER_FMT_UNPACK(fmt_, 0x7F, 7)
+
+#define AI_BUFFER_FMT_SET_BITS(bits_) AI_BUFFER_FMT_PACK((bits_), 0x7F, 7)
+
+#define AI_BUFFER_FMT_GET_FBITS(fmt_) ((ai_i8)AI_BUFFER_FMT_UNPACK(fmt_, 0x7F, 0) - 64)
+
+#define AI_BUFFER_FMT_SET_FBITS(fbits_) AI_BUFFER_FMT_PACK((fbits_) + 64, 0x7F, 0)
+
+#define AI_BUFFER_FMT_SET(type_id_, sign_bit_, float_bit_, bits_, fbits_) \
+ AI_BUFFER_FMT_OBJ(AI_BUFFER_FMT_PACK(float_bit_, 0x1, 24) | \
+ AI_BUFFER_FMT_PACK(sign_bit_, 0x1, 23) | AI_BUFFER_FMT_PACK(0, 0x3, 21) | \
+ AI_BUFFER_FMT_PACK(type_id_, 0xF, 17) | AI_BUFFER_FMT_PACK(0, 0x7, 14) | \
+ AI_BUFFER_FMT_SET_BITS(bits_) | AI_BUFFER_FMT_SET_FBITS(fbits_))
+
+#define AI_BUFFER_FMT_GET(fmt_) (AI_BUFFER_FMT_OBJ(fmt_) & 0x01FFFFFF)
+
+#define AI_BUFFER_FORMAT(buf_) AI_BUFFER_FMT_GET((buf_)->format)
+#define AI_BUFFER_WIDTH(buf_) ((buf_)->width)
+#define AI_BUFFER_HEIGHT(buf_) ((buf_)->height)
+#define AI_BUFFER_CHANNELS(buf_) ((buf_)->channels)
+#define AI_BUFFER_N_BATCHES(buf_) ((buf_)->n_batches)
+#define AI_BUFFER_DATA(buf_, type_) ((type_*)((buf_)->data))
+
+#define AI_BUFFER_META_INFO(buf_) ((buf_)->meta_info)
+
+#define AI_BUFFER_META_INFO_INTQ(meta_) \
+ ((meta_) && ((meta_)->flags & AI_BUFFER_META_HAS_INTQ_INFO)) ? ((meta_)->intq_info) \
+ : NULL // NOLINT
+
+#define AI_BUFFER_META_INFO_INTQ_GET_SCALE(meta_, pos_) \
+ ((AI_BUFFER_META_INFO_INTQ(meta_)) \
+ ? AI_INTQ_INFO_LIST_SCALE(AI_BUFFER_META_INFO_INTQ(meta_), ai_float, pos_) \
+ : 0)
+
+#define AI_BUFFER_META_INFO_INTQ_GET_ZEROPOINT(meta_, pos_) \
Review comment:
nit: can't see where this is used
##########
File path: src/runtime/crt/contrib/stm32/ai_platform.h
##########
@@ -0,0 +1,383 @@
+/*
+ * 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.
+ */
+
+/*!
+ * \file ai_platform.h
+ * \brief Definitions of AI platform public APIs types
+ */
+
+// LINT_C_FILE
+
+#ifndef AI_PLATFORM_H
+#define AI_PLATFORM_H
+#pragma once
+
+#include <inttypes.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#ifndef AI_PLATFORM_API_MAJOR
+#define AI_PLATFORM_API_MAJOR (0)
+#endif
+#ifndef AI_PLATFORM_API_MINOR
+#define AI_PLATFORM_API_MINOR (6)
+#endif
+#ifndef AI_PLATFORM_API_MICRO
+#define AI_PLATFORM_API_MICRO (0)
+#endif
+
+#define AI_PLATFORM_API_VERSION \
+ AI_VERSION(AI_PLATFORM_API_MAJOR, AI_PLATFORM_API_MINOR, AI_PLATFORM_API_MICRO)
+
+#ifndef AI_TOOLS_API_VERSION_MAJOR
+#define AI_TOOLS_API_VERSION_MAJOR (1)
+#endif
+#ifndef AI_TOOLS_API_VERSION_MINOR
+#define AI_TOOLS_API_VERSION_MINOR (4)
+#endif
+#ifndef AI_TOOLS_API_VERSION_MICRO
+#define AI_TOOLS_API_VERSION_MICRO (0)
+#endif
+
+#define AI_TOOLS_API_VERSION \
+ AI_VERSION(AI_TOOLS_API_VERSION_MAJOR, AI_TOOLS_API_VERSION_MINOR, AI_TOOLS_API_VERSION_MICRO)
+
+#define AI_TOOLS_API_VERSION_1_3 AI_VERSION(1, 3, 0)
+
+/******************************************************************************/
+#ifdef __cplusplus
+#define AI_API_DECLARE_BEGIN extern "C" {
+#define AI_API_DECLARE_END }
+#else
+#include <stdbool.h>
+#define AI_API_DECLARE_BEGIN /* AI_API_DECLARE_BEGIN */
+#define AI_API_DECLARE_END /* AI_API_DECLARE_END */
+#endif
+
+/******************************************************************************/
+#if defined(_MSC_VER)
+#define AI_API_ENTRY __declspec(dllexport)
+#define AI_ALIGNED(x) /* AI_ALIGNED(x) */
+#elif defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
+#define AI_API_ENTRY /* AI_API_ENTRY */
+#define AI_ALIGNED(x) AI_CONCAT(AI_ALIGNED_, x)
+#define AI_ALIGNED_1 _Pragma("data_alignment = 1")
+#define AI_ALIGNED_2 _Pragma("data_alignment = 2")
+#define AI_ALIGNED_4 _Pragma("data_alignment = 4")
+#define AI_ALIGNED_8 _Pragma("data_alignment = 8")
+#define AI_ALIGNED_16 _Pragma("data_alignment = 16")
+#define AI_ALIGNED_32 _Pragma("data_alignment = 32")
+#elif defined(__CC_ARM)
+#define AI_API_ENTRY __attribute__((visibility("default")))
+#define AI_ALIGNED(x) __attribute__((aligned(x)))
+/* Keil disallows anonymous union initialization by default */
+#pragma anon_unions
+#elif defined(__GNUC__)
+#define AI_API_ENTRY __attribute__((visibility("default")))
+#define AI_ALIGNED(x) __attribute__((aligned(x)))
+#else
+/* Dynamic libraries are not supported by the compiler */
+#define AI_API_ENTRY /* AI_API_ENTRY */
+#define AI_ALIGNED(x) /* AI_ALIGNED(x) */
+#endif
+
+#define AI_HANDLE_PTR(ptr_) ((ai_handle)(ptr_))
+#define AI_HANDLE_NULL AI_HANDLE_PTR(NULL)
+
+#define AI_HANDLE_FUNC_PTR(func) ((ai_handle_func)(func))
+
+#define AI_NETWORK_PARAMS_INIT(params_, activations_) \
+ { .params = params_, .activations = activations_ }
+
+/*! ai_intq_info struct handlers **********************************************/
+#define INTQ_CONST const
+// #define INTQ_CONST
+
+#define AI_INTQ_INFO_LIST(list_) ((list_)->info)
+
+#define AI_INTQ_INFO_LIST_FLAGS(list_) ((list_) ? (list_)->flags : 0)
+
+#define AI_INTQ_INFO_LIST_SIZE(list_) ((list_) ? (list_)->size : 0)
+
+#define AI_HAS_INTQ_INFO_LIST(list_) ((list_) ? (((list_)->info) && ((list_)->size > 0)) : false)
+
+#define AI_INTQ_INFO_LIST_SCALE(list_, type_, pos_) \
+ (((list_) && (list_)->info && ((pos_) < (list_)->size)) \
+ ? ((type_*)((list_)->info->scale))[(pos_)] \
+ : 0)
+
+#define AI_INTQ_INFO_LIST_ZEROPOINT(list_, type_, pos_) \
+ (((list_) && (list_)->info && ((pos_) < (list_)->size)) \
+ ? ((type_*)((list_)->info->zeropoint))[(pos_)] \
+ : 0)
+
+/*! ai_buffer format handlers *************************************************/
+
+/*!
+ * @enum buffer format definition
+ * @ingroup ai_platform
+ *
+ * 32 bit signed format list.
+ */
+typedef int32_t ai_buffer_format;
+
+/*! ai_buffer_meta flags ******************************************************/
+#define AI_BUFFER_META_HAS_INTQ_INFO (0x1U << 0)
+#define AI_BUFFER_META_FLAG_SCALE_FLOAT (0x1U << 0)
+#define AI_BUFFER_META_FLAG_ZEROPOINT_U8 (0x1U << 1)
+#define AI_BUFFER_META_FLAG_ZEROPOINT_S8 (0x1U << 2)
+
+/*! ai_buffer format variable flags *******************************************/
+#define AI_BUFFER_FMT_TYPE_NONE (0x0)
+#define AI_BUFFER_FMT_TYPE_FLOAT (0x1)
+#define AI_BUFFER_FMT_TYPE_Q (0x2)
+#define AI_BUFFER_FMT_TYPE_BOOL (0x3)
+
+#define AI_BUFFER_FMT_FLAG_CONST (0x1U << 30)
+#define AI_BUFFER_FMT_FLAG_STATIC (0x1U << 29)
+#define AI_BUFFER_FMT_FLAG_IS_IO (0x1U << 27)
+
+#define AI_BUFFER_FMT_PACK(value_, mask_, bits_) (((value_) & (mask_)) << (bits_))
+
+#define AI_BUFFER_FMT_UNPACK(fmt_, mask_, bits_) ((AI_BUFFER_FMT_OBJ(fmt_) >> (bits_)) & (mask_))
+
+#define AI_BUFFER_FMT_OBJ(fmt_) ((ai_buffer_format)(fmt_))
+
+#define AI_BUFFER_FMT_GET_FLOAT(fmt_) AI_BUFFER_FMT_UNPACK(fmt_, 0x1, 24)
+
+#define AI_BUFFER_FMT_GET_SIGN(fmt_) AI_BUFFER_FMT_UNPACK(fmt_, 0x1, 23)
+
+#define AI_BUFFER_FMT_GET_TYPE(fmt_) AI_BUFFER_FMT_UNPACK(fmt_, 0xF, 17)
+
+#define AI_BUFFER_FMT_GET_BITS(fmt_) AI_BUFFER_FMT_UNPACK(fmt_, 0x7F, 7)
+
+#define AI_BUFFER_FMT_SET_BITS(bits_) AI_BUFFER_FMT_PACK((bits_), 0x7F, 7)
+
+#define AI_BUFFER_FMT_GET_FBITS(fmt_) ((ai_i8)AI_BUFFER_FMT_UNPACK(fmt_, 0x7F, 0) - 64)
+
+#define AI_BUFFER_FMT_SET_FBITS(fbits_) AI_BUFFER_FMT_PACK((fbits_) + 64, 0x7F, 0)
+
+#define AI_BUFFER_FMT_SET(type_id_, sign_bit_, float_bit_, bits_, fbits_) \
+ AI_BUFFER_FMT_OBJ(AI_BUFFER_FMT_PACK(float_bit_, 0x1, 24) | \
+ AI_BUFFER_FMT_PACK(sign_bit_, 0x1, 23) | AI_BUFFER_FMT_PACK(0, 0x3, 21) | \
+ AI_BUFFER_FMT_PACK(type_id_, 0xF, 17) | AI_BUFFER_FMT_PACK(0, 0x7, 14) | \
+ AI_BUFFER_FMT_SET_BITS(bits_) | AI_BUFFER_FMT_SET_FBITS(fbits_))
+
+#define AI_BUFFER_FMT_GET(fmt_) (AI_BUFFER_FMT_OBJ(fmt_) & 0x01FFFFFF)
+
+#define AI_BUFFER_FORMAT(buf_) AI_BUFFER_FMT_GET((buf_)->format)
+#define AI_BUFFER_WIDTH(buf_) ((buf_)->width)
+#define AI_BUFFER_HEIGHT(buf_) ((buf_)->height)
+#define AI_BUFFER_CHANNELS(buf_) ((buf_)->channels)
+#define AI_BUFFER_N_BATCHES(buf_) ((buf_)->n_batches)
+#define AI_BUFFER_DATA(buf_, type_) ((type_*)((buf_)->data))
+
+#define AI_BUFFER_META_INFO(buf_) ((buf_)->meta_info)
+
+#define AI_BUFFER_META_INFO_INTQ(meta_) \
+ ((meta_) && ((meta_)->flags & AI_BUFFER_META_HAS_INTQ_INFO)) ? ((meta_)->intq_info) \
+ : NULL // NOLINT
+
+#define AI_BUFFER_META_INFO_INTQ_GET_SCALE(meta_, pos_) \
+ ((AI_BUFFER_META_INFO_INTQ(meta_)) \
+ ? AI_INTQ_INFO_LIST_SCALE(AI_BUFFER_META_INFO_INTQ(meta_), ai_float, pos_) \
+ : 0)
+
+#define AI_BUFFER_META_INFO_INTQ_GET_ZEROPOINT(meta_, pos_) \
+ ((AI_BUFFER_META_INFO_INTQ(meta_)) \
+ ? ((AI_INTQ_INFO_LIST_FLAGS(AI_BUFFER_META_INFO_INTQ(meta_)) & \
+ AI_BUFFER_META_FLAG_ZEROPOINT_U8) \
+ ? AI_INTQ_INFO_LIST_ZEROPOINT(AI_BUFFER_META_INFO_INTQ(meta_), ai_u8, pos_) \
+ : AI_INTQ_INFO_LIST_ZEROPOINT(AI_BUFFER_META_INFO_INTQ(meta_), ai_i8, pos_)) \
+ : 0)
+
+#define AI_BUFFER_META_INFO_INIT(flags_, intq_info_) \
+ { .flags = (flags_), .intq_info = AI_PACK(intq_info_) }
+
+#define AI_BUFFER_SIZE(buf_) (((buf_)->width) * ((buf_)->height) * ((buf_)->channels))
+
+#define AI_BUFFER_BYTE_SIZE(count_, fmt_) ((((count_)*AI_BUFFER_FMT_GET_BITS(fmt_)) + 4) >> 3)
+
+/*!
+ * @enum buffer formats enum list
+ * @ingroup ai_platform
+ *
+ * List of supported ai_buffer format types.
+ */
+enum {
+ AI_BUFFER_FORMAT_NONE = AI_BUFFER_FMT_SET(AI_BUFFER_FMT_TYPE_NONE, 0, 0, 0, 0),
+ AI_BUFFER_FORMAT_FLOAT = AI_BUFFER_FMT_SET(AI_BUFFER_FMT_TYPE_FLOAT, 1, 1, 32, 0),
+
+ AI_BUFFER_FORMAT_U8 = AI_BUFFER_FMT_SET(AI_BUFFER_FMT_TYPE_Q, 0, 0, 8, 0),
+ AI_BUFFER_FORMAT_U16 = AI_BUFFER_FMT_SET(AI_BUFFER_FMT_TYPE_Q, 0, 0, 16, 0),
+ AI_BUFFER_FORMAT_S8 = AI_BUFFER_FMT_SET(AI_BUFFER_FMT_TYPE_Q, 1, 0, 8, 0),
+ AI_BUFFER_FORMAT_S16 = AI_BUFFER_FMT_SET(AI_BUFFER_FMT_TYPE_Q, 1, 0, 16, 0),
+
+ AI_BUFFER_FORMAT_Q = AI_BUFFER_FMT_SET(AI_BUFFER_FMT_TYPE_Q, 1, 0, 0, 0),
+ AI_BUFFER_FORMAT_Q7 = AI_BUFFER_FMT_SET(AI_BUFFER_FMT_TYPE_Q, 1, 0, 8, 7),
+ AI_BUFFER_FORMAT_Q15 = AI_BUFFER_FMT_SET(AI_BUFFER_FMT_TYPE_Q, 1, 0, 16, 15),
+
+ AI_BUFFER_FORMAT_UQ = AI_BUFFER_FMT_SET(AI_BUFFER_FMT_TYPE_Q, 0, 0, 0, 0),
+ AI_BUFFER_FORMAT_UQ7 = AI_BUFFER_FMT_SET(AI_BUFFER_FMT_TYPE_Q, 0, 0, 8, 7),
+ AI_BUFFER_FORMAT_UQ15 = AI_BUFFER_FMT_SET(AI_BUFFER_FMT_TYPE_Q, 0, 0, 16, 15),
+
+ AI_BUFFER_FORMAT_BOOL = AI_BUFFER_FMT_SET(AI_BUFFER_FMT_TYPE_BOOL, 0, 0, 8, 0),
+};
+
+/******************************************************************************/
+
+/* printf formats */
+#define SSIZET_FMT "%" PRIu32
+#define AII32_FMT "%" PRId32
+#define AIU32_FMT "%" PRIu32
+
+typedef uint8_t ai_custom_type_signature;
+
+typedef void* ai_handle;
+
+typedef void (*ai_handle_func)(void*);
+
+typedef float ai_float;
+typedef double ai_double;
+
+typedef bool ai_bool;
+
+typedef uint32_t ai_size;
+
+typedef uintptr_t ai_uptr;
+
+typedef unsigned int ai_uint;
+typedef uint8_t ai_u8;
+typedef uint16_t ai_u16;
+typedef uint32_t ai_u32;
+typedef uint64_t ai_u64;
+
+typedef int ai_int;
+typedef int8_t ai_i8;
+typedef int16_t ai_i16;
+typedef int32_t ai_i32;
+typedef int64_t ai_i64;
+
+typedef uint32_t ai_signature;
+
+/******************************************************************************/
+/*!
+ * @struct ai_intq_info
+ * @ingroup ai_platform
+ * @brief an element of the ai_intq_info_list entry. It reports an array for the
+ * scale and zeropoint values for each buffer. Optional flags are also present
+ */
+typedef struct ai_intq_info_ {
+ INTQ_CONST ai_float* scale;
+ INTQ_CONST ai_handle zeropoint;
+} ai_intq_info;
+
+/*!
+ * @struct ai_intq_info_list
+ * @ingroup ai_platform
+ * @brief list reporting meta info for quantized networks integer support
+ * when size > 1 it means a per channel out quantization
+ */
+typedef struct ai_intq_info_list_ {
+ ai_u16 flags; /*!< optional flags to store intq info attributes */
+ ai_u16 size; /*!< number of elements in the the intq_info list */
+ INTQ_CONST ai_intq_info* info; /*!< pointer to an array of quant info */
+} ai_intq_info_list;
+
+/******************************************************************************/
+/*!
+ * @struct ai_buffer_meta_info
+ * @ingroup ai_platform
+ * @brief Optional meta attributes associated with the I/O buffer.
+ * This datastruct is used also for network querying, where the data field may
+ * may be NULL.
+ */
+typedef struct ai_buffer_meta_info_ {
+ ai_u32 flags; /*!< meta info flags */
+ ai_intq_info_list* intq_info; /*!< meta info related to integer format */
+} ai_buffer_meta_info;
+
+/*!
+ * @struct ai_buffer
+ * @ingroup ai_platform
+ * @brief Memory buffer storing data (optional) with a shape, size and type.
+ * This datastruct is used also for network querying, where the data field may
+ * may be NULL.
+ */
+typedef struct ai_buffer_ {
+ ai_buffer_format format; /*!< buffer format */
+ ai_u16 n_batches; /*!< number of batches in the buffer */
+ ai_u16 height; /*!< buffer height dimension */
+ ai_u16 width; /*!< buffer width dimension */
+ ai_u32 channels; /*!< buffer number of channels */
+ ai_handle data; /*!< pointer to buffer data */
+ ai_buffer_meta_info* meta_info; /*!< pointer to buffer metadata info */
+} ai_buffer;
+
+/*!
+ * @struct ai_platform_version
+ * @ingroup ai_platform
+ * @brief Datastruct storing platform version info
+ */
+typedef struct ai_platform_version_ {
+ ai_u8 major;
+ ai_u8 minor;
+ ai_u8 micro;
+ ai_u8 reserved;
+} ai_platform_version;
+
+/*!
+ * @struct ai_network_report
+ * @ingroup ai_platform
+ *
+ * Datastructure to query a network report with some relevant network detail.
+ */
+typedef struct ai_network_report_ {
+ const char* model_name;
+ const char* model_signature;
+ const char* model_datetime;
+
+ const char* compile_datetime;
+
+ const char* runtime_revision;
+ ai_platform_version runtime_version;
+
+ const char* tool_revision;
+ ai_platform_version tool_version;
+ ai_platform_version tool_api_version;
+
+ ai_platform_version api_version;
+ ai_platform_version interface_api_version;
+
+ ai_u32 n_macc;
+
+ ai_u16 n_inputs;
+ ai_u16 n_outputs;
+ ai_buffer* inputs;
+ ai_buffer* outputs;
+
+ ai_buffer activations;
+ ai_buffer params;
+
+ ai_u32 n_nodes;
+
+ ai_signature signature;
+} ai_network_report;
Review comment:
i'm not sure i see this struct used at all in the codebase. aside from a couple typedefs used in `ai_runtime_api.h`, i'm not sure this file is used. can we either delete it or pare it down considerably? i'm not sure if maybe this file is typically provided by X-Cube, but it would be great to provide a minimal bridge between TVM and X-Cube by just including the typedefs needed for `ai_runtime_api.h`.
##########
File path: src/runtime/crt/contrib/stm32/ai_platform.h
##########
@@ -0,0 +1,383 @@
+/*
+ * 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.
+ */
+
+/*!
+ * \file ai_platform.h
+ * \brief Definitions of AI platform public APIs types
+ */
+
+// LINT_C_FILE
+
+#ifndef AI_PLATFORM_H
+#define AI_PLATFORM_H
+#pragma once
+
+#include <inttypes.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#ifndef AI_PLATFORM_API_MAJOR
+#define AI_PLATFORM_API_MAJOR (0)
+#endif
+#ifndef AI_PLATFORM_API_MINOR
+#define AI_PLATFORM_API_MINOR (6)
+#endif
+#ifndef AI_PLATFORM_API_MICRO
+#define AI_PLATFORM_API_MICRO (0)
+#endif
+
+#define AI_PLATFORM_API_VERSION \
+ AI_VERSION(AI_PLATFORM_API_MAJOR, AI_PLATFORM_API_MINOR, AI_PLATFORM_API_MICRO)
+
+#ifndef AI_TOOLS_API_VERSION_MAJOR
+#define AI_TOOLS_API_VERSION_MAJOR (1)
+#endif
+#ifndef AI_TOOLS_API_VERSION_MINOR
+#define AI_TOOLS_API_VERSION_MINOR (4)
+#endif
+#ifndef AI_TOOLS_API_VERSION_MICRO
+#define AI_TOOLS_API_VERSION_MICRO (0)
+#endif
+
+#define AI_TOOLS_API_VERSION \
+ AI_VERSION(AI_TOOLS_API_VERSION_MAJOR, AI_TOOLS_API_VERSION_MINOR, AI_TOOLS_API_VERSION_MICRO)
+
+#define AI_TOOLS_API_VERSION_1_3 AI_VERSION(1, 3, 0)
+
+/******************************************************************************/
+#ifdef __cplusplus
+#define AI_API_DECLARE_BEGIN extern "C" {
+#define AI_API_DECLARE_END }
+#else
+#include <stdbool.h>
+#define AI_API_DECLARE_BEGIN /* AI_API_DECLARE_BEGIN */
+#define AI_API_DECLARE_END /* AI_API_DECLARE_END */
+#endif
+
+/******************************************************************************/
+#if defined(_MSC_VER)
+#define AI_API_ENTRY __declspec(dllexport)
+#define AI_ALIGNED(x) /* AI_ALIGNED(x) */
+#elif defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
+#define AI_API_ENTRY /* AI_API_ENTRY */
+#define AI_ALIGNED(x) AI_CONCAT(AI_ALIGNED_, x)
+#define AI_ALIGNED_1 _Pragma("data_alignment = 1")
+#define AI_ALIGNED_2 _Pragma("data_alignment = 2")
+#define AI_ALIGNED_4 _Pragma("data_alignment = 4")
+#define AI_ALIGNED_8 _Pragma("data_alignment = 8")
+#define AI_ALIGNED_16 _Pragma("data_alignment = 16")
+#define AI_ALIGNED_32 _Pragma("data_alignment = 32")
+#elif defined(__CC_ARM)
+#define AI_API_ENTRY __attribute__((visibility("default")))
+#define AI_ALIGNED(x) __attribute__((aligned(x)))
+/* Keil disallows anonymous union initialization by default */
+#pragma anon_unions
+#elif defined(__GNUC__)
+#define AI_API_ENTRY __attribute__((visibility("default")))
+#define AI_ALIGNED(x) __attribute__((aligned(x)))
+#else
+/* Dynamic libraries are not supported by the compiler */
+#define AI_API_ENTRY /* AI_API_ENTRY */
+#define AI_ALIGNED(x) /* AI_ALIGNED(x) */
+#endif
+
+#define AI_HANDLE_PTR(ptr_) ((ai_handle)(ptr_))
+#define AI_HANDLE_NULL AI_HANDLE_PTR(NULL)
+
+#define AI_HANDLE_FUNC_PTR(func) ((ai_handle_func)(func))
+
+#define AI_NETWORK_PARAMS_INIT(params_, activations_) \
+ { .params = params_, .activations = activations_ }
+
+/*! ai_intq_info struct handlers **********************************************/
+#define INTQ_CONST const
+// #define INTQ_CONST
+
+#define AI_INTQ_INFO_LIST(list_) ((list_)->info)
+
+#define AI_INTQ_INFO_LIST_FLAGS(list_) ((list_) ? (list_)->flags : 0)
+
+#define AI_INTQ_INFO_LIST_SIZE(list_) ((list_) ? (list_)->size : 0)
+
+#define AI_HAS_INTQ_INFO_LIST(list_) ((list_) ? (((list_)->info) && ((list_)->size > 0)) : false)
+
+#define AI_INTQ_INFO_LIST_SCALE(list_, type_, pos_) \
+ (((list_) && (list_)->info && ((pos_) < (list_)->size)) \
+ ? ((type_*)((list_)->info->scale))[(pos_)] \
+ : 0)
+
+#define AI_INTQ_INFO_LIST_ZEROPOINT(list_, type_, pos_) \
+ (((list_) && (list_)->info && ((pos_) < (list_)->size)) \
+ ? ((type_*)((list_)->info->zeropoint))[(pos_)] \
+ : 0)
+
+/*! ai_buffer format handlers *************************************************/
+
+/*!
+ * @enum buffer format definition
+ * @ingroup ai_platform
+ *
+ * 32 bit signed format list.
+ */
+typedef int32_t ai_buffer_format;
+
+/*! ai_buffer_meta flags ******************************************************/
+#define AI_BUFFER_META_HAS_INTQ_INFO (0x1U << 0)
+#define AI_BUFFER_META_FLAG_SCALE_FLOAT (0x1U << 0)
+#define AI_BUFFER_META_FLAG_ZEROPOINT_U8 (0x1U << 1)
+#define AI_BUFFER_META_FLAG_ZEROPOINT_S8 (0x1U << 2)
+
+/*! ai_buffer format variable flags *******************************************/
+#define AI_BUFFER_FMT_TYPE_NONE (0x0)
+#define AI_BUFFER_FMT_TYPE_FLOAT (0x1)
+#define AI_BUFFER_FMT_TYPE_Q (0x2)
+#define AI_BUFFER_FMT_TYPE_BOOL (0x3)
+
+#define AI_BUFFER_FMT_FLAG_CONST (0x1U << 30)
+#define AI_BUFFER_FMT_FLAG_STATIC (0x1U << 29)
+#define AI_BUFFER_FMT_FLAG_IS_IO (0x1U << 27)
+
+#define AI_BUFFER_FMT_PACK(value_, mask_, bits_) (((value_) & (mask_)) << (bits_))
+
+#define AI_BUFFER_FMT_UNPACK(fmt_, mask_, bits_) ((AI_BUFFER_FMT_OBJ(fmt_) >> (bits_)) & (mask_))
+
+#define AI_BUFFER_FMT_OBJ(fmt_) ((ai_buffer_format)(fmt_))
+
+#define AI_BUFFER_FMT_GET_FLOAT(fmt_) AI_BUFFER_FMT_UNPACK(fmt_, 0x1, 24)
+
+#define AI_BUFFER_FMT_GET_SIGN(fmt_) AI_BUFFER_FMT_UNPACK(fmt_, 0x1, 23)
+
+#define AI_BUFFER_FMT_GET_TYPE(fmt_) AI_BUFFER_FMT_UNPACK(fmt_, 0xF, 17)
+
+#define AI_BUFFER_FMT_GET_BITS(fmt_) AI_BUFFER_FMT_UNPACK(fmt_, 0x7F, 7)
+
+#define AI_BUFFER_FMT_SET_BITS(bits_) AI_BUFFER_FMT_PACK((bits_), 0x7F, 7)
+
+#define AI_BUFFER_FMT_GET_FBITS(fmt_) ((ai_i8)AI_BUFFER_FMT_UNPACK(fmt_, 0x7F, 0) - 64)
+
+#define AI_BUFFER_FMT_SET_FBITS(fbits_) AI_BUFFER_FMT_PACK((fbits_) + 64, 0x7F, 0)
+
+#define AI_BUFFER_FMT_SET(type_id_, sign_bit_, float_bit_, bits_, fbits_) \
+ AI_BUFFER_FMT_OBJ(AI_BUFFER_FMT_PACK(float_bit_, 0x1, 24) | \
+ AI_BUFFER_FMT_PACK(sign_bit_, 0x1, 23) | AI_BUFFER_FMT_PACK(0, 0x3, 21) | \
+ AI_BUFFER_FMT_PACK(type_id_, 0xF, 17) | AI_BUFFER_FMT_PACK(0, 0x7, 14) | \
+ AI_BUFFER_FMT_SET_BITS(bits_) | AI_BUFFER_FMT_SET_FBITS(fbits_))
+
+#define AI_BUFFER_FMT_GET(fmt_) (AI_BUFFER_FMT_OBJ(fmt_) & 0x01FFFFFF)
+
+#define AI_BUFFER_FORMAT(buf_) AI_BUFFER_FMT_GET((buf_)->format)
+#define AI_BUFFER_WIDTH(buf_) ((buf_)->width)
+#define AI_BUFFER_HEIGHT(buf_) ((buf_)->height)
+#define AI_BUFFER_CHANNELS(buf_) ((buf_)->channels)
+#define AI_BUFFER_N_BATCHES(buf_) ((buf_)->n_batches)
+#define AI_BUFFER_DATA(buf_, type_) ((type_*)((buf_)->data))
+
+#define AI_BUFFER_META_INFO(buf_) ((buf_)->meta_info)
+
+#define AI_BUFFER_META_INFO_INTQ(meta_) \
+ ((meta_) && ((meta_)->flags & AI_BUFFER_META_HAS_INTQ_INFO)) ? ((meta_)->intq_info) \
+ : NULL // NOLINT
+
+#define AI_BUFFER_META_INFO_INTQ_GET_SCALE(meta_, pos_) \
Review comment:
nit: can't see where this is used
##########
File path: src/runtime/crt/contrib/stm32/ai_platform.h
##########
@@ -0,0 +1,383 @@
+/*
+ * 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.
+ */
+
+/*!
+ * \file ai_platform.h
+ * \brief Definitions of AI platform public APIs types
+ */
+
+// LINT_C_FILE
+
+#ifndef AI_PLATFORM_H
+#define AI_PLATFORM_H
+#pragma once
+
+#include <inttypes.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#ifndef AI_PLATFORM_API_MAJOR
+#define AI_PLATFORM_API_MAJOR (0)
+#endif
+#ifndef AI_PLATFORM_API_MINOR
+#define AI_PLATFORM_API_MINOR (6)
+#endif
+#ifndef AI_PLATFORM_API_MICRO
+#define AI_PLATFORM_API_MICRO (0)
+#endif
+
+#define AI_PLATFORM_API_VERSION \
+ AI_VERSION(AI_PLATFORM_API_MAJOR, AI_PLATFORM_API_MINOR, AI_PLATFORM_API_MICRO)
+
+#ifndef AI_TOOLS_API_VERSION_MAJOR
+#define AI_TOOLS_API_VERSION_MAJOR (1)
+#endif
+#ifndef AI_TOOLS_API_VERSION_MINOR
+#define AI_TOOLS_API_VERSION_MINOR (4)
+#endif
+#ifndef AI_TOOLS_API_VERSION_MICRO
+#define AI_TOOLS_API_VERSION_MICRO (0)
+#endif
+
+#define AI_TOOLS_API_VERSION \
+ AI_VERSION(AI_TOOLS_API_VERSION_MAJOR, AI_TOOLS_API_VERSION_MINOR, AI_TOOLS_API_VERSION_MICRO)
+
+#define AI_TOOLS_API_VERSION_1_3 AI_VERSION(1, 3, 0)
+
+/******************************************************************************/
+#ifdef __cplusplus
+#define AI_API_DECLARE_BEGIN extern "C" {
+#define AI_API_DECLARE_END }
+#else
+#include <stdbool.h>
+#define AI_API_DECLARE_BEGIN /* AI_API_DECLARE_BEGIN */
+#define AI_API_DECLARE_END /* AI_API_DECLARE_END */
+#endif
+
+/******************************************************************************/
+#if defined(_MSC_VER)
+#define AI_API_ENTRY __declspec(dllexport)
+#define AI_ALIGNED(x) /* AI_ALIGNED(x) */
+#elif defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
+#define AI_API_ENTRY /* AI_API_ENTRY */
+#define AI_ALIGNED(x) AI_CONCAT(AI_ALIGNED_, x)
+#define AI_ALIGNED_1 _Pragma("data_alignment = 1")
+#define AI_ALIGNED_2 _Pragma("data_alignment = 2")
+#define AI_ALIGNED_4 _Pragma("data_alignment = 4")
+#define AI_ALIGNED_8 _Pragma("data_alignment = 8")
+#define AI_ALIGNED_16 _Pragma("data_alignment = 16")
+#define AI_ALIGNED_32 _Pragma("data_alignment = 32")
+#elif defined(__CC_ARM)
+#define AI_API_ENTRY __attribute__((visibility("default")))
+#define AI_ALIGNED(x) __attribute__((aligned(x)))
+/* Keil disallows anonymous union initialization by default */
+#pragma anon_unions
+#elif defined(__GNUC__)
+#define AI_API_ENTRY __attribute__((visibility("default")))
+#define AI_ALIGNED(x) __attribute__((aligned(x)))
+#else
+/* Dynamic libraries are not supported by the compiler */
+#define AI_API_ENTRY /* AI_API_ENTRY */
+#define AI_ALIGNED(x) /* AI_ALIGNED(x) */
+#endif
+
+#define AI_HANDLE_PTR(ptr_) ((ai_handle)(ptr_))
+#define AI_HANDLE_NULL AI_HANDLE_PTR(NULL)
+
+#define AI_HANDLE_FUNC_PTR(func) ((ai_handle_func)(func))
+
+#define AI_NETWORK_PARAMS_INIT(params_, activations_) \
+ { .params = params_, .activations = activations_ }
+
+/*! ai_intq_info struct handlers **********************************************/
+#define INTQ_CONST const
+// #define INTQ_CONST
+
+#define AI_INTQ_INFO_LIST(list_) ((list_)->info)
+
+#define AI_INTQ_INFO_LIST_FLAGS(list_) ((list_) ? (list_)->flags : 0)
+
+#define AI_INTQ_INFO_LIST_SIZE(list_) ((list_) ? (list_)->size : 0)
+
+#define AI_HAS_INTQ_INFO_LIST(list_) ((list_) ? (((list_)->info) && ((list_)->size > 0)) : false)
+
+#define AI_INTQ_INFO_LIST_SCALE(list_, type_, pos_) \
+ (((list_) && (list_)->info && ((pos_) < (list_)->size)) \
+ ? ((type_*)((list_)->info->scale))[(pos_)] \
+ : 0)
+
+#define AI_INTQ_INFO_LIST_ZEROPOINT(list_, type_, pos_) \
+ (((list_) && (list_)->info && ((pos_) < (list_)->size)) \
+ ? ((type_*)((list_)->info->zeropoint))[(pos_)] \
+ : 0)
+
+/*! ai_buffer format handlers *************************************************/
+
+/*!
+ * @enum buffer format definition
+ * @ingroup ai_platform
+ *
+ * 32 bit signed format list.
+ */
+typedef int32_t ai_buffer_format;
+
+/*! ai_buffer_meta flags ******************************************************/
+#define AI_BUFFER_META_HAS_INTQ_INFO (0x1U << 0)
+#define AI_BUFFER_META_FLAG_SCALE_FLOAT (0x1U << 0)
+#define AI_BUFFER_META_FLAG_ZEROPOINT_U8 (0x1U << 1)
+#define AI_BUFFER_META_FLAG_ZEROPOINT_S8 (0x1U << 2)
+
+/*! ai_buffer format variable flags *******************************************/
+#define AI_BUFFER_FMT_TYPE_NONE (0x0)
+#define AI_BUFFER_FMT_TYPE_FLOAT (0x1)
+#define AI_BUFFER_FMT_TYPE_Q (0x2)
+#define AI_BUFFER_FMT_TYPE_BOOL (0x3)
+
+#define AI_BUFFER_FMT_FLAG_CONST (0x1U << 30)
+#define AI_BUFFER_FMT_FLAG_STATIC (0x1U << 29)
+#define AI_BUFFER_FMT_FLAG_IS_IO (0x1U << 27)
+
+#define AI_BUFFER_FMT_PACK(value_, mask_, bits_) (((value_) & (mask_)) << (bits_))
+
+#define AI_BUFFER_FMT_UNPACK(fmt_, mask_, bits_) ((AI_BUFFER_FMT_OBJ(fmt_) >> (bits_)) & (mask_))
+
+#define AI_BUFFER_FMT_OBJ(fmt_) ((ai_buffer_format)(fmt_))
+
+#define AI_BUFFER_FMT_GET_FLOAT(fmt_) AI_BUFFER_FMT_UNPACK(fmt_, 0x1, 24)
+
+#define AI_BUFFER_FMT_GET_SIGN(fmt_) AI_BUFFER_FMT_UNPACK(fmt_, 0x1, 23)
+
+#define AI_BUFFER_FMT_GET_TYPE(fmt_) AI_BUFFER_FMT_UNPACK(fmt_, 0xF, 17)
+
+#define AI_BUFFER_FMT_GET_BITS(fmt_) AI_BUFFER_FMT_UNPACK(fmt_, 0x7F, 7)
+
+#define AI_BUFFER_FMT_SET_BITS(bits_) AI_BUFFER_FMT_PACK((bits_), 0x7F, 7)
+
+#define AI_BUFFER_FMT_GET_FBITS(fmt_) ((ai_i8)AI_BUFFER_FMT_UNPACK(fmt_, 0x7F, 0) - 64)
+
+#define AI_BUFFER_FMT_SET_FBITS(fbits_) AI_BUFFER_FMT_PACK((fbits_) + 64, 0x7F, 0)
+
+#define AI_BUFFER_FMT_SET(type_id_, sign_bit_, float_bit_, bits_, fbits_) \
+ AI_BUFFER_FMT_OBJ(AI_BUFFER_FMT_PACK(float_bit_, 0x1, 24) | \
+ AI_BUFFER_FMT_PACK(sign_bit_, 0x1, 23) | AI_BUFFER_FMT_PACK(0, 0x3, 21) | \
+ AI_BUFFER_FMT_PACK(type_id_, 0xF, 17) | AI_BUFFER_FMT_PACK(0, 0x7, 14) | \
+ AI_BUFFER_FMT_SET_BITS(bits_) | AI_BUFFER_FMT_SET_FBITS(fbits_))
+
+#define AI_BUFFER_FMT_GET(fmt_) (AI_BUFFER_FMT_OBJ(fmt_) & 0x01FFFFFF)
+
+#define AI_BUFFER_FORMAT(buf_) AI_BUFFER_FMT_GET((buf_)->format)
+#define AI_BUFFER_WIDTH(buf_) ((buf_)->width)
+#define AI_BUFFER_HEIGHT(buf_) ((buf_)->height)
+#define AI_BUFFER_CHANNELS(buf_) ((buf_)->channels)
+#define AI_BUFFER_N_BATCHES(buf_) ((buf_)->n_batches)
+#define AI_BUFFER_DATA(buf_, type_) ((type_*)((buf_)->data))
+
+#define AI_BUFFER_META_INFO(buf_) ((buf_)->meta_info)
+
+#define AI_BUFFER_META_INFO_INTQ(meta_) \
+ ((meta_) && ((meta_)->flags & AI_BUFFER_META_HAS_INTQ_INFO)) ? ((meta_)->intq_info) \
+ : NULL // NOLINT
+
+#define AI_BUFFER_META_INFO_INTQ_GET_SCALE(meta_, pos_) \
+ ((AI_BUFFER_META_INFO_INTQ(meta_)) \
+ ? AI_INTQ_INFO_LIST_SCALE(AI_BUFFER_META_INFO_INTQ(meta_), ai_float, pos_) \
+ : 0)
+
+#define AI_BUFFER_META_INFO_INTQ_GET_ZEROPOINT(meta_, pos_) \
+ ((AI_BUFFER_META_INFO_INTQ(meta_)) \
+ ? ((AI_INTQ_INFO_LIST_FLAGS(AI_BUFFER_META_INFO_INTQ(meta_)) & \
+ AI_BUFFER_META_FLAG_ZEROPOINT_U8) \
+ ? AI_INTQ_INFO_LIST_ZEROPOINT(AI_BUFFER_META_INFO_INTQ(meta_), ai_u8, pos_) \
+ : AI_INTQ_INFO_LIST_ZEROPOINT(AI_BUFFER_META_INFO_INTQ(meta_), ai_i8, pos_)) \
+ : 0)
+
+#define AI_BUFFER_META_INFO_INIT(flags_, intq_info_) \
+ { .flags = (flags_), .intq_info = AI_PACK(intq_info_) }
+
+#define AI_BUFFER_SIZE(buf_) (((buf_)->width) * ((buf_)->height) * ((buf_)->channels))
+
+#define AI_BUFFER_BYTE_SIZE(count_, fmt_) ((((count_)*AI_BUFFER_FMT_GET_BITS(fmt_)) + 4) >> 3)
Review comment:
nit: can't see where this is used
##########
File path: src/runtime/crt/contrib/stm32/ai_platform.h
##########
@@ -0,0 +1,383 @@
+/*
+ * 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.
+ */
+
+/*!
+ * \file ai_platform.h
+ * \brief Definitions of AI platform public APIs types
+ */
+
+// LINT_C_FILE
+
+#ifndef AI_PLATFORM_H
+#define AI_PLATFORM_H
+#pragma once
+
+#include <inttypes.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#ifndef AI_PLATFORM_API_MAJOR
+#define AI_PLATFORM_API_MAJOR (0)
+#endif
+#ifndef AI_PLATFORM_API_MINOR
+#define AI_PLATFORM_API_MINOR (6)
+#endif
+#ifndef AI_PLATFORM_API_MICRO
+#define AI_PLATFORM_API_MICRO (0)
+#endif
+
+#define AI_PLATFORM_API_VERSION \
+ AI_VERSION(AI_PLATFORM_API_MAJOR, AI_PLATFORM_API_MINOR, AI_PLATFORM_API_MICRO)
+
+#ifndef AI_TOOLS_API_VERSION_MAJOR
+#define AI_TOOLS_API_VERSION_MAJOR (1)
+#endif
+#ifndef AI_TOOLS_API_VERSION_MINOR
+#define AI_TOOLS_API_VERSION_MINOR (4)
+#endif
+#ifndef AI_TOOLS_API_VERSION_MICRO
+#define AI_TOOLS_API_VERSION_MICRO (0)
+#endif
+
+#define AI_TOOLS_API_VERSION \
+ AI_VERSION(AI_TOOLS_API_VERSION_MAJOR, AI_TOOLS_API_VERSION_MINOR, AI_TOOLS_API_VERSION_MICRO)
+
+#define AI_TOOLS_API_VERSION_1_3 AI_VERSION(1, 3, 0)
+
+/******************************************************************************/
+#ifdef __cplusplus
+#define AI_API_DECLARE_BEGIN extern "C" {
+#define AI_API_DECLARE_END }
+#else
+#include <stdbool.h>
+#define AI_API_DECLARE_BEGIN /* AI_API_DECLARE_BEGIN */
+#define AI_API_DECLARE_END /* AI_API_DECLARE_END */
+#endif
+
+/******************************************************************************/
+#if defined(_MSC_VER)
+#define AI_API_ENTRY __declspec(dllexport)
+#define AI_ALIGNED(x) /* AI_ALIGNED(x) */
+#elif defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
+#define AI_API_ENTRY /* AI_API_ENTRY */
+#define AI_ALIGNED(x) AI_CONCAT(AI_ALIGNED_, x)
+#define AI_ALIGNED_1 _Pragma("data_alignment = 1")
+#define AI_ALIGNED_2 _Pragma("data_alignment = 2")
+#define AI_ALIGNED_4 _Pragma("data_alignment = 4")
+#define AI_ALIGNED_8 _Pragma("data_alignment = 8")
+#define AI_ALIGNED_16 _Pragma("data_alignment = 16")
+#define AI_ALIGNED_32 _Pragma("data_alignment = 32")
+#elif defined(__CC_ARM)
+#define AI_API_ENTRY __attribute__((visibility("default")))
+#define AI_ALIGNED(x) __attribute__((aligned(x)))
+/* Keil disallows anonymous union initialization by default */
+#pragma anon_unions
+#elif defined(__GNUC__)
+#define AI_API_ENTRY __attribute__((visibility("default")))
+#define AI_ALIGNED(x) __attribute__((aligned(x)))
+#else
+/* Dynamic libraries are not supported by the compiler */
+#define AI_API_ENTRY /* AI_API_ENTRY */
+#define AI_ALIGNED(x) /* AI_ALIGNED(x) */
+#endif
+
+#define AI_HANDLE_PTR(ptr_) ((ai_handle)(ptr_))
+#define AI_HANDLE_NULL AI_HANDLE_PTR(NULL)
+
+#define AI_HANDLE_FUNC_PTR(func) ((ai_handle_func)(func))
Review comment:
nit: can't see where this is used
##########
File path: src/runtime/crt/contrib/stm32/ai_platform.h
##########
@@ -0,0 +1,383 @@
+/*
+ * 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.
+ */
+
+/*!
+ * \file ai_platform.h
+ * \brief Definitions of AI platform public APIs types
+ */
+
+// LINT_C_FILE
+
+#ifndef AI_PLATFORM_H
+#define AI_PLATFORM_H
+#pragma once
+
+#include <inttypes.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#ifndef AI_PLATFORM_API_MAJOR
+#define AI_PLATFORM_API_MAJOR (0)
+#endif
+#ifndef AI_PLATFORM_API_MINOR
+#define AI_PLATFORM_API_MINOR (6)
+#endif
+#ifndef AI_PLATFORM_API_MICRO
+#define AI_PLATFORM_API_MICRO (0)
+#endif
+
+#define AI_PLATFORM_API_VERSION \
+ AI_VERSION(AI_PLATFORM_API_MAJOR, AI_PLATFORM_API_MINOR, AI_PLATFORM_API_MICRO)
+
+#ifndef AI_TOOLS_API_VERSION_MAJOR
+#define AI_TOOLS_API_VERSION_MAJOR (1)
+#endif
+#ifndef AI_TOOLS_API_VERSION_MINOR
+#define AI_TOOLS_API_VERSION_MINOR (4)
+#endif
+#ifndef AI_TOOLS_API_VERSION_MICRO
+#define AI_TOOLS_API_VERSION_MICRO (0)
+#endif
+
+#define AI_TOOLS_API_VERSION \
+ AI_VERSION(AI_TOOLS_API_VERSION_MAJOR, AI_TOOLS_API_VERSION_MINOR, AI_TOOLS_API_VERSION_MICRO)
+
+#define AI_TOOLS_API_VERSION_1_3 AI_VERSION(1, 3, 0)
+
+/******************************************************************************/
+#ifdef __cplusplus
+#define AI_API_DECLARE_BEGIN extern "C" {
+#define AI_API_DECLARE_END }
+#else
+#include <stdbool.h>
+#define AI_API_DECLARE_BEGIN /* AI_API_DECLARE_BEGIN */
+#define AI_API_DECLARE_END /* AI_API_DECLARE_END */
+#endif
+
+/******************************************************************************/
+#if defined(_MSC_VER)
+#define AI_API_ENTRY __declspec(dllexport)
+#define AI_ALIGNED(x) /* AI_ALIGNED(x) */
+#elif defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
+#define AI_API_ENTRY /* AI_API_ENTRY */
+#define AI_ALIGNED(x) AI_CONCAT(AI_ALIGNED_, x)
+#define AI_ALIGNED_1 _Pragma("data_alignment = 1")
+#define AI_ALIGNED_2 _Pragma("data_alignment = 2")
+#define AI_ALIGNED_4 _Pragma("data_alignment = 4")
+#define AI_ALIGNED_8 _Pragma("data_alignment = 8")
+#define AI_ALIGNED_16 _Pragma("data_alignment = 16")
+#define AI_ALIGNED_32 _Pragma("data_alignment = 32")
+#elif defined(__CC_ARM)
+#define AI_API_ENTRY __attribute__((visibility("default")))
+#define AI_ALIGNED(x) __attribute__((aligned(x)))
+/* Keil disallows anonymous union initialization by default */
+#pragma anon_unions
+#elif defined(__GNUC__)
+#define AI_API_ENTRY __attribute__((visibility("default")))
+#define AI_ALIGNED(x) __attribute__((aligned(x)))
+#else
+/* Dynamic libraries are not supported by the compiler */
+#define AI_API_ENTRY /* AI_API_ENTRY */
+#define AI_ALIGNED(x) /* AI_ALIGNED(x) */
+#endif
+
+#define AI_HANDLE_PTR(ptr_) ((ai_handle)(ptr_))
+#define AI_HANDLE_NULL AI_HANDLE_PTR(NULL)
+
+#define AI_HANDLE_FUNC_PTR(func) ((ai_handle_func)(func))
+
+#define AI_NETWORK_PARAMS_INIT(params_, activations_) \
+ { .params = params_, .activations = activations_ }
+
+/*! ai_intq_info struct handlers **********************************************/
+#define INTQ_CONST const
+// #define INTQ_CONST
+
+#define AI_INTQ_INFO_LIST(list_) ((list_)->info)
+
+#define AI_INTQ_INFO_LIST_FLAGS(list_) ((list_) ? (list_)->flags : 0)
+
+#define AI_INTQ_INFO_LIST_SIZE(list_) ((list_) ? (list_)->size : 0)
+
+#define AI_HAS_INTQ_INFO_LIST(list_) ((list_) ? (((list_)->info) && ((list_)->size > 0)) : false)
+
+#define AI_INTQ_INFO_LIST_SCALE(list_, type_, pos_) \
+ (((list_) && (list_)->info && ((pos_) < (list_)->size)) \
+ ? ((type_*)((list_)->info->scale))[(pos_)] \
+ : 0)
+
+#define AI_INTQ_INFO_LIST_ZEROPOINT(list_, type_, pos_) \
+ (((list_) && (list_)->info && ((pos_) < (list_)->size)) \
+ ? ((type_*)((list_)->info->zeropoint))[(pos_)] \
+ : 0)
+
+/*! ai_buffer format handlers *************************************************/
+
+/*!
+ * @enum buffer format definition
+ * @ingroup ai_platform
+ *
+ * 32 bit signed format list.
+ */
+typedef int32_t ai_buffer_format;
+
+/*! ai_buffer_meta flags ******************************************************/
+#define AI_BUFFER_META_HAS_INTQ_INFO (0x1U << 0)
+#define AI_BUFFER_META_FLAG_SCALE_FLOAT (0x1U << 0)
+#define AI_BUFFER_META_FLAG_ZEROPOINT_U8 (0x1U << 1)
+#define AI_BUFFER_META_FLAG_ZEROPOINT_S8 (0x1U << 2)
+
+/*! ai_buffer format variable flags *******************************************/
+#define AI_BUFFER_FMT_TYPE_NONE (0x0)
+#define AI_BUFFER_FMT_TYPE_FLOAT (0x1)
+#define AI_BUFFER_FMT_TYPE_Q (0x2)
+#define AI_BUFFER_FMT_TYPE_BOOL (0x3)
+
+#define AI_BUFFER_FMT_FLAG_CONST (0x1U << 30)
+#define AI_BUFFER_FMT_FLAG_STATIC (0x1U << 29)
+#define AI_BUFFER_FMT_FLAG_IS_IO (0x1U << 27)
+
+#define AI_BUFFER_FMT_PACK(value_, mask_, bits_) (((value_) & (mask_)) << (bits_))
+
+#define AI_BUFFER_FMT_UNPACK(fmt_, mask_, bits_) ((AI_BUFFER_FMT_OBJ(fmt_) >> (bits_)) & (mask_))
+
+#define AI_BUFFER_FMT_OBJ(fmt_) ((ai_buffer_format)(fmt_))
+
+#define AI_BUFFER_FMT_GET_FLOAT(fmt_) AI_BUFFER_FMT_UNPACK(fmt_, 0x1, 24)
+
+#define AI_BUFFER_FMT_GET_SIGN(fmt_) AI_BUFFER_FMT_UNPACK(fmt_, 0x1, 23)
+
+#define AI_BUFFER_FMT_GET_TYPE(fmt_) AI_BUFFER_FMT_UNPACK(fmt_, 0xF, 17)
+
+#define AI_BUFFER_FMT_GET_BITS(fmt_) AI_BUFFER_FMT_UNPACK(fmt_, 0x7F, 7)
+
+#define AI_BUFFER_FMT_SET_BITS(bits_) AI_BUFFER_FMT_PACK((bits_), 0x7F, 7)
+
+#define AI_BUFFER_FMT_GET_FBITS(fmt_) ((ai_i8)AI_BUFFER_FMT_UNPACK(fmt_, 0x7F, 0) - 64)
+
+#define AI_BUFFER_FMT_SET_FBITS(fbits_) AI_BUFFER_FMT_PACK((fbits_) + 64, 0x7F, 0)
+
+#define AI_BUFFER_FMT_SET(type_id_, sign_bit_, float_bit_, bits_, fbits_) \
+ AI_BUFFER_FMT_OBJ(AI_BUFFER_FMT_PACK(float_bit_, 0x1, 24) | \
+ AI_BUFFER_FMT_PACK(sign_bit_, 0x1, 23) | AI_BUFFER_FMT_PACK(0, 0x3, 21) | \
+ AI_BUFFER_FMT_PACK(type_id_, 0xF, 17) | AI_BUFFER_FMT_PACK(0, 0x7, 14) | \
+ AI_BUFFER_FMT_SET_BITS(bits_) | AI_BUFFER_FMT_SET_FBITS(fbits_))
+
+#define AI_BUFFER_FMT_GET(fmt_) (AI_BUFFER_FMT_OBJ(fmt_) & 0x01FFFFFF)
+
+#define AI_BUFFER_FORMAT(buf_) AI_BUFFER_FMT_GET((buf_)->format)
+#define AI_BUFFER_WIDTH(buf_) ((buf_)->width)
+#define AI_BUFFER_HEIGHT(buf_) ((buf_)->height)
+#define AI_BUFFER_CHANNELS(buf_) ((buf_)->channels)
+#define AI_BUFFER_N_BATCHES(buf_) ((buf_)->n_batches)
+#define AI_BUFFER_DATA(buf_, type_) ((type_*)((buf_)->data))
+
+#define AI_BUFFER_META_INFO(buf_) ((buf_)->meta_info)
+
+#define AI_BUFFER_META_INFO_INTQ(meta_) \
+ ((meta_) && ((meta_)->flags & AI_BUFFER_META_HAS_INTQ_INFO)) ? ((meta_)->intq_info) \
+ : NULL // NOLINT
+
+#define AI_BUFFER_META_INFO_INTQ_GET_SCALE(meta_, pos_) \
+ ((AI_BUFFER_META_INFO_INTQ(meta_)) \
+ ? AI_INTQ_INFO_LIST_SCALE(AI_BUFFER_META_INFO_INTQ(meta_), ai_float, pos_) \
+ : 0)
+
+#define AI_BUFFER_META_INFO_INTQ_GET_ZEROPOINT(meta_, pos_) \
+ ((AI_BUFFER_META_INFO_INTQ(meta_)) \
+ ? ((AI_INTQ_INFO_LIST_FLAGS(AI_BUFFER_META_INFO_INTQ(meta_)) & \
+ AI_BUFFER_META_FLAG_ZEROPOINT_U8) \
+ ? AI_INTQ_INFO_LIST_ZEROPOINT(AI_BUFFER_META_INFO_INTQ(meta_), ai_u8, pos_) \
+ : AI_INTQ_INFO_LIST_ZEROPOINT(AI_BUFFER_META_INFO_INTQ(meta_), ai_i8, pos_)) \
+ : 0)
+
+#define AI_BUFFER_META_INFO_INIT(flags_, intq_info_) \
+ { .flags = (flags_), .intq_info = AI_PACK(intq_info_) }
+
+#define AI_BUFFER_SIZE(buf_) (((buf_)->width) * ((buf_)->height) * ((buf_)->channels))
+
+#define AI_BUFFER_BYTE_SIZE(count_, fmt_) ((((count_)*AI_BUFFER_FMT_GET_BITS(fmt_)) + 4) >> 3)
+
+/*!
+ * @enum buffer formats enum list
+ * @ingroup ai_platform
+ *
+ * List of supported ai_buffer format types.
+ */
+enum {
+ AI_BUFFER_FORMAT_NONE = AI_BUFFER_FMT_SET(AI_BUFFER_FMT_TYPE_NONE, 0, 0, 0, 0),
+ AI_BUFFER_FORMAT_FLOAT = AI_BUFFER_FMT_SET(AI_BUFFER_FMT_TYPE_FLOAT, 1, 1, 32, 0),
+
+ AI_BUFFER_FORMAT_U8 = AI_BUFFER_FMT_SET(AI_BUFFER_FMT_TYPE_Q, 0, 0, 8, 0),
+ AI_BUFFER_FORMAT_U16 = AI_BUFFER_FMT_SET(AI_BUFFER_FMT_TYPE_Q, 0, 0, 16, 0),
+ AI_BUFFER_FORMAT_S8 = AI_BUFFER_FMT_SET(AI_BUFFER_FMT_TYPE_Q, 1, 0, 8, 0),
+ AI_BUFFER_FORMAT_S16 = AI_BUFFER_FMT_SET(AI_BUFFER_FMT_TYPE_Q, 1, 0, 16, 0),
+
+ AI_BUFFER_FORMAT_Q = AI_BUFFER_FMT_SET(AI_BUFFER_FMT_TYPE_Q, 1, 0, 0, 0),
+ AI_BUFFER_FORMAT_Q7 = AI_BUFFER_FMT_SET(AI_BUFFER_FMT_TYPE_Q, 1, 0, 8, 7),
+ AI_BUFFER_FORMAT_Q15 = AI_BUFFER_FMT_SET(AI_BUFFER_FMT_TYPE_Q, 1, 0, 16, 15),
+
+ AI_BUFFER_FORMAT_UQ = AI_BUFFER_FMT_SET(AI_BUFFER_FMT_TYPE_Q, 0, 0, 0, 0),
+ AI_BUFFER_FORMAT_UQ7 = AI_BUFFER_FMT_SET(AI_BUFFER_FMT_TYPE_Q, 0, 0, 8, 7),
+ AI_BUFFER_FORMAT_UQ15 = AI_BUFFER_FMT_SET(AI_BUFFER_FMT_TYPE_Q, 0, 0, 16, 15),
+
+ AI_BUFFER_FORMAT_BOOL = AI_BUFFER_FMT_SET(AI_BUFFER_FMT_TYPE_BOOL, 0, 0, 8, 0),
+};
+
+/******************************************************************************/
+
+/* printf formats */
+#define SSIZET_FMT "%" PRIu32
+#define AII32_FMT "%" PRId32
+#define AIU32_FMT "%" PRIu32
+
+typedef uint8_t ai_custom_type_signature;
+
+typedef void* ai_handle;
+
+typedef void (*ai_handle_func)(void*);
Review comment:
nit: can't see where this is used
##########
File path: src/runtime/crt/contrib/stm32/ai_platform.h
##########
@@ -0,0 +1,383 @@
+/*
+ * 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.
+ */
+
+/*!
+ * \file ai_platform.h
+ * \brief Definitions of AI platform public APIs types
+ */
+
+// LINT_C_FILE
+
+#ifndef AI_PLATFORM_H
+#define AI_PLATFORM_H
+#pragma once
+
+#include <inttypes.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#ifndef AI_PLATFORM_API_MAJOR
+#define AI_PLATFORM_API_MAJOR (0)
+#endif
+#ifndef AI_PLATFORM_API_MINOR
+#define AI_PLATFORM_API_MINOR (6)
+#endif
+#ifndef AI_PLATFORM_API_MICRO
+#define AI_PLATFORM_API_MICRO (0)
+#endif
+
+#define AI_PLATFORM_API_VERSION \
+ AI_VERSION(AI_PLATFORM_API_MAJOR, AI_PLATFORM_API_MINOR, AI_PLATFORM_API_MICRO)
+
+#ifndef AI_TOOLS_API_VERSION_MAJOR
+#define AI_TOOLS_API_VERSION_MAJOR (1)
+#endif
+#ifndef AI_TOOLS_API_VERSION_MINOR
+#define AI_TOOLS_API_VERSION_MINOR (4)
+#endif
+#ifndef AI_TOOLS_API_VERSION_MICRO
+#define AI_TOOLS_API_VERSION_MICRO (0)
+#endif
+
+#define AI_TOOLS_API_VERSION \
+ AI_VERSION(AI_TOOLS_API_VERSION_MAJOR, AI_TOOLS_API_VERSION_MINOR, AI_TOOLS_API_VERSION_MICRO)
+
+#define AI_TOOLS_API_VERSION_1_3 AI_VERSION(1, 3, 0)
+
+/******************************************************************************/
+#ifdef __cplusplus
+#define AI_API_DECLARE_BEGIN extern "C" {
+#define AI_API_DECLARE_END }
+#else
+#include <stdbool.h>
+#define AI_API_DECLARE_BEGIN /* AI_API_DECLARE_BEGIN */
+#define AI_API_DECLARE_END /* AI_API_DECLARE_END */
+#endif
+
+/******************************************************************************/
+#if defined(_MSC_VER)
+#define AI_API_ENTRY __declspec(dllexport)
+#define AI_ALIGNED(x) /* AI_ALIGNED(x) */
+#elif defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
+#define AI_API_ENTRY /* AI_API_ENTRY */
+#define AI_ALIGNED(x) AI_CONCAT(AI_ALIGNED_, x)
+#define AI_ALIGNED_1 _Pragma("data_alignment = 1")
+#define AI_ALIGNED_2 _Pragma("data_alignment = 2")
+#define AI_ALIGNED_4 _Pragma("data_alignment = 4")
+#define AI_ALIGNED_8 _Pragma("data_alignment = 8")
+#define AI_ALIGNED_16 _Pragma("data_alignment = 16")
+#define AI_ALIGNED_32 _Pragma("data_alignment = 32")
+#elif defined(__CC_ARM)
+#define AI_API_ENTRY __attribute__((visibility("default")))
+#define AI_ALIGNED(x) __attribute__((aligned(x)))
+/* Keil disallows anonymous union initialization by default */
+#pragma anon_unions
+#elif defined(__GNUC__)
+#define AI_API_ENTRY __attribute__((visibility("default")))
+#define AI_ALIGNED(x) __attribute__((aligned(x)))
+#else
+/* Dynamic libraries are not supported by the compiler */
+#define AI_API_ENTRY /* AI_API_ENTRY */
+#define AI_ALIGNED(x) /* AI_ALIGNED(x) */
+#endif
+
+#define AI_HANDLE_PTR(ptr_) ((ai_handle)(ptr_))
+#define AI_HANDLE_NULL AI_HANDLE_PTR(NULL)
+
+#define AI_HANDLE_FUNC_PTR(func) ((ai_handle_func)(func))
+
+#define AI_NETWORK_PARAMS_INIT(params_, activations_) \
+ { .params = params_, .activations = activations_ }
+
+/*! ai_intq_info struct handlers **********************************************/
+#define INTQ_CONST const
+// #define INTQ_CONST
+
+#define AI_INTQ_INFO_LIST(list_) ((list_)->info)
+
+#define AI_INTQ_INFO_LIST_FLAGS(list_) ((list_) ? (list_)->flags : 0)
+
+#define AI_INTQ_INFO_LIST_SIZE(list_) ((list_) ? (list_)->size : 0)
+
+#define AI_HAS_INTQ_INFO_LIST(list_) ((list_) ? (((list_)->info) && ((list_)->size > 0)) : false)
+
+#define AI_INTQ_INFO_LIST_SCALE(list_, type_, pos_) \
+ (((list_) && (list_)->info && ((pos_) < (list_)->size)) \
+ ? ((type_*)((list_)->info->scale))[(pos_)] \
+ : 0)
+
+#define AI_INTQ_INFO_LIST_ZEROPOINT(list_, type_, pos_) \
+ (((list_) && (list_)->info && ((pos_) < (list_)->size)) \
+ ? ((type_*)((list_)->info->zeropoint))[(pos_)] \
+ : 0)
+
+/*! ai_buffer format handlers *************************************************/
+
+/*!
+ * @enum buffer format definition
+ * @ingroup ai_platform
+ *
+ * 32 bit signed format list.
+ */
+typedef int32_t ai_buffer_format;
+
+/*! ai_buffer_meta flags ******************************************************/
+#define AI_BUFFER_META_HAS_INTQ_INFO (0x1U << 0)
+#define AI_BUFFER_META_FLAG_SCALE_FLOAT (0x1U << 0)
+#define AI_BUFFER_META_FLAG_ZEROPOINT_U8 (0x1U << 1)
+#define AI_BUFFER_META_FLAG_ZEROPOINT_S8 (0x1U << 2)
+
+/*! ai_buffer format variable flags *******************************************/
+#define AI_BUFFER_FMT_TYPE_NONE (0x0)
+#define AI_BUFFER_FMT_TYPE_FLOAT (0x1)
+#define AI_BUFFER_FMT_TYPE_Q (0x2)
+#define AI_BUFFER_FMT_TYPE_BOOL (0x3)
+
+#define AI_BUFFER_FMT_FLAG_CONST (0x1U << 30)
+#define AI_BUFFER_FMT_FLAG_STATIC (0x1U << 29)
+#define AI_BUFFER_FMT_FLAG_IS_IO (0x1U << 27)
+
+#define AI_BUFFER_FMT_PACK(value_, mask_, bits_) (((value_) & (mask_)) << (bits_))
+
+#define AI_BUFFER_FMT_UNPACK(fmt_, mask_, bits_) ((AI_BUFFER_FMT_OBJ(fmt_) >> (bits_)) & (mask_))
+
+#define AI_BUFFER_FMT_OBJ(fmt_) ((ai_buffer_format)(fmt_))
+
+#define AI_BUFFER_FMT_GET_FLOAT(fmt_) AI_BUFFER_FMT_UNPACK(fmt_, 0x1, 24)
+
+#define AI_BUFFER_FMT_GET_SIGN(fmt_) AI_BUFFER_FMT_UNPACK(fmt_, 0x1, 23)
+
+#define AI_BUFFER_FMT_GET_TYPE(fmt_) AI_BUFFER_FMT_UNPACK(fmt_, 0xF, 17)
+
+#define AI_BUFFER_FMT_GET_BITS(fmt_) AI_BUFFER_FMT_UNPACK(fmt_, 0x7F, 7)
+
+#define AI_BUFFER_FMT_SET_BITS(bits_) AI_BUFFER_FMT_PACK((bits_), 0x7F, 7)
+
+#define AI_BUFFER_FMT_GET_FBITS(fmt_) ((ai_i8)AI_BUFFER_FMT_UNPACK(fmt_, 0x7F, 0) - 64)
+
+#define AI_BUFFER_FMT_SET_FBITS(fbits_) AI_BUFFER_FMT_PACK((fbits_) + 64, 0x7F, 0)
+
+#define AI_BUFFER_FMT_SET(type_id_, sign_bit_, float_bit_, bits_, fbits_) \
+ AI_BUFFER_FMT_OBJ(AI_BUFFER_FMT_PACK(float_bit_, 0x1, 24) | \
+ AI_BUFFER_FMT_PACK(sign_bit_, 0x1, 23) | AI_BUFFER_FMT_PACK(0, 0x3, 21) | \
+ AI_BUFFER_FMT_PACK(type_id_, 0xF, 17) | AI_BUFFER_FMT_PACK(0, 0x7, 14) | \
+ AI_BUFFER_FMT_SET_BITS(bits_) | AI_BUFFER_FMT_SET_FBITS(fbits_))
+
+#define AI_BUFFER_FMT_GET(fmt_) (AI_BUFFER_FMT_OBJ(fmt_) & 0x01FFFFFF)
+
+#define AI_BUFFER_FORMAT(buf_) AI_BUFFER_FMT_GET((buf_)->format)
+#define AI_BUFFER_WIDTH(buf_) ((buf_)->width)
+#define AI_BUFFER_HEIGHT(buf_) ((buf_)->height)
+#define AI_BUFFER_CHANNELS(buf_) ((buf_)->channels)
+#define AI_BUFFER_N_BATCHES(buf_) ((buf_)->n_batches)
+#define AI_BUFFER_DATA(buf_, type_) ((type_*)((buf_)->data))
+
+#define AI_BUFFER_META_INFO(buf_) ((buf_)->meta_info)
+
+#define AI_BUFFER_META_INFO_INTQ(meta_) \
+ ((meta_) && ((meta_)->flags & AI_BUFFER_META_HAS_INTQ_INFO)) ? ((meta_)->intq_info) \
+ : NULL // NOLINT
+
+#define AI_BUFFER_META_INFO_INTQ_GET_SCALE(meta_, pos_) \
+ ((AI_BUFFER_META_INFO_INTQ(meta_)) \
+ ? AI_INTQ_INFO_LIST_SCALE(AI_BUFFER_META_INFO_INTQ(meta_), ai_float, pos_) \
+ : 0)
+
+#define AI_BUFFER_META_INFO_INTQ_GET_ZEROPOINT(meta_, pos_) \
+ ((AI_BUFFER_META_INFO_INTQ(meta_)) \
+ ? ((AI_INTQ_INFO_LIST_FLAGS(AI_BUFFER_META_INFO_INTQ(meta_)) & \
+ AI_BUFFER_META_FLAG_ZEROPOINT_U8) \
+ ? AI_INTQ_INFO_LIST_ZEROPOINT(AI_BUFFER_META_INFO_INTQ(meta_), ai_u8, pos_) \
+ : AI_INTQ_INFO_LIST_ZEROPOINT(AI_BUFFER_META_INFO_INTQ(meta_), ai_i8, pos_)) \
+ : 0)
+
+#define AI_BUFFER_META_INFO_INIT(flags_, intq_info_) \
+ { .flags = (flags_), .intq_info = AI_PACK(intq_info_) }
+
+#define AI_BUFFER_SIZE(buf_) (((buf_)->width) * ((buf_)->height) * ((buf_)->channels))
Review comment:
nit: can't see where this is used
##########
File path: src/runtime/crt/contrib/stm32/ai_platform.h
##########
@@ -0,0 +1,383 @@
+/*
+ * 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.
+ */
+
+/*!
+ * \file ai_platform.h
+ * \brief Definitions of AI platform public APIs types
+ */
+
+// LINT_C_FILE
+
+#ifndef AI_PLATFORM_H
+#define AI_PLATFORM_H
+#pragma once
+
+#include <inttypes.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#ifndef AI_PLATFORM_API_MAJOR
+#define AI_PLATFORM_API_MAJOR (0)
+#endif
+#ifndef AI_PLATFORM_API_MINOR
+#define AI_PLATFORM_API_MINOR (6)
+#endif
+#ifndef AI_PLATFORM_API_MICRO
+#define AI_PLATFORM_API_MICRO (0)
+#endif
+
+#define AI_PLATFORM_API_VERSION \
+ AI_VERSION(AI_PLATFORM_API_MAJOR, AI_PLATFORM_API_MINOR, AI_PLATFORM_API_MICRO)
+
+#ifndef AI_TOOLS_API_VERSION_MAJOR
+#define AI_TOOLS_API_VERSION_MAJOR (1)
+#endif
+#ifndef AI_TOOLS_API_VERSION_MINOR
+#define AI_TOOLS_API_VERSION_MINOR (4)
+#endif
+#ifndef AI_TOOLS_API_VERSION_MICRO
+#define AI_TOOLS_API_VERSION_MICRO (0)
+#endif
+
+#define AI_TOOLS_API_VERSION \
+ AI_VERSION(AI_TOOLS_API_VERSION_MAJOR, AI_TOOLS_API_VERSION_MINOR, AI_TOOLS_API_VERSION_MICRO)
+
+#define AI_TOOLS_API_VERSION_1_3 AI_VERSION(1, 3, 0)
+
+/******************************************************************************/
+#ifdef __cplusplus
+#define AI_API_DECLARE_BEGIN extern "C" {
+#define AI_API_DECLARE_END }
+#else
+#include <stdbool.h>
+#define AI_API_DECLARE_BEGIN /* AI_API_DECLARE_BEGIN */
+#define AI_API_DECLARE_END /* AI_API_DECLARE_END */
+#endif
+
+/******************************************************************************/
+#if defined(_MSC_VER)
+#define AI_API_ENTRY __declspec(dllexport)
+#define AI_ALIGNED(x) /* AI_ALIGNED(x) */
+#elif defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
+#define AI_API_ENTRY /* AI_API_ENTRY */
+#define AI_ALIGNED(x) AI_CONCAT(AI_ALIGNED_, x)
+#define AI_ALIGNED_1 _Pragma("data_alignment = 1")
+#define AI_ALIGNED_2 _Pragma("data_alignment = 2")
+#define AI_ALIGNED_4 _Pragma("data_alignment = 4")
+#define AI_ALIGNED_8 _Pragma("data_alignment = 8")
+#define AI_ALIGNED_16 _Pragma("data_alignment = 16")
+#define AI_ALIGNED_32 _Pragma("data_alignment = 32")
+#elif defined(__CC_ARM)
+#define AI_API_ENTRY __attribute__((visibility("default")))
+#define AI_ALIGNED(x) __attribute__((aligned(x)))
+/* Keil disallows anonymous union initialization by default */
+#pragma anon_unions
+#elif defined(__GNUC__)
+#define AI_API_ENTRY __attribute__((visibility("default")))
+#define AI_ALIGNED(x) __attribute__((aligned(x)))
+#else
+/* Dynamic libraries are not supported by the compiler */
+#define AI_API_ENTRY /* AI_API_ENTRY */
+#define AI_ALIGNED(x) /* AI_ALIGNED(x) */
+#endif
+
+#define AI_HANDLE_PTR(ptr_) ((ai_handle)(ptr_))
+#define AI_HANDLE_NULL AI_HANDLE_PTR(NULL)
+
+#define AI_HANDLE_FUNC_PTR(func) ((ai_handle_func)(func))
+
+#define AI_NETWORK_PARAMS_INIT(params_, activations_) \
Review comment:
nit: can't see where this is used
##########
File path: python/tvm/contrib/stm32/BaseEmitter.py
##########
@@ -0,0 +1,1257 @@
+# 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.
+
+# pylint: disable=line-too-long
+
+"""Code emission for the STM32 targets."""
+
+import json
+import os
+import re
+import tarfile
+
+from datetime import datetime
+
+import numpy as np
+
+import tvm
+from tvm.contrib import utils
+
+AI_TOOLS_VERSION_MAJOR = 1
+AI_TOOLS_VERSION_MINOR = 8
+AI_TOOLS_VERSION_MICRO = 0
+
+AI_API_VERSION_MAJOR = 1
+AI_API_VERSION_MINOR = 0
+AI_API_VERSION_MICRO = 0
+
+AI_TOOLS_REVISION = "v1"
+
+DBAR = "=" * 60
+
+
+def _fix_name(node_name):
+ """Replace ':' with '_' in names like 'InputImg:0'"""
+ return node_name.replace(":", "_")
+
+
+def get_input_tensor_name(node_name):
+ return _fix_name(node_name)
+
+
+def get_output_tensor_name(node_name, idx):
+ return _fix_name(node_name) + "_" + str(idx)
+
+
+def get_tensor_data_name(tensor_name):
+ return tensor_name + ".dltensor.data"
+
+
+def get_node_args_name(node_name):
+ return _fix_name(node_name) + "_args"
+
+
+def get_node_arg_types_name(node_name):
+ return _fix_name(node_name) + "_arg_type_ids"
+
+
+def _get_type_size(dltype):
+
+ if dltype in ("uint64", "int64"):
+ return 8
+ if dltype in ("uint32", "int32", "float32"):
+ return 4
+ if dltype in ("uint16", "int16"):
+ return 2
+ if dltype in ("uint8", "int8"):
+ return 1
+
+ raise ValueError(f"Data type {dltype} is not supported")
+
+
+def _get_type_data(dltype):
+
+ if dltype == "uint64":
+ return "kDLUInt, 64, 1"
+ if dltype == "int64":
+ return "kDLInt, 64, 1"
+ if dltype == "float32":
+ return "kDLFloat, 32, 1"
+ if dltype == "uint32":
+ return "kDLUInt, 32, 1"
+ if dltype == "int32":
+ return "kDLInt, 32, 1"
+ if dltype == "uint16":
+ return "kDLUInt, 16, 1"
+ if dltype == "int16":
+ return "kDLInt, 16, 1"
+ if dltype == "uint8":
+ return "kDLUInt, 8, 1"
+ if dltype == "int8":
+ return "kDLInt, 8, 1"
+
+ raise ValueError(f"Data type {dltype} is not supported")
+
+
+def get_aligned_offset(offset, dltype):
+
+ align = _get_type_size(dltype)
+
+ if offset % align != 0:
+ offset = offset + (align - offset % align)
+
+ return offset
+
+
+def _get_tensor_elts(dims):
+ size = 1
+ for dim in dims:
+ size = size * dim
+ return size
+
+
+def get_tensor_size(dims, dltype):
+ size = _get_tensor_elts(dims)
+ return size * _get_type_size(dltype)
+
+
+def _emit_tensor_shape(dl_tensor_name, ndim, shape, strides, out_c):
+ out_c.write(f"AI_STATIC int64_t {dl_tensor_name}_shape[{ndim}] = {{{shape[1:-1]}}}; \n")
+ assert strides is None, f"###Error: non-compact tensors are not handled yet."
+ out_c.write(f"AI_STATIC int64_t {dl_tensor_name}_strides[{ndim}] = {{}}; \n")
+
+
+def _emit_tensor_quant(dl_tensor_name, quantization_map, out_c):
+
+ if dl_tensor_name in quantization_map:
+ quantization = quantization_map[dl_tensor_name]
+ else:
+ quantization = None
+
+ if quantization is not None:
+ # minval = quantization['min']
+ # maxval = quantization['max']
+ scale = quantization["scale"]
+ zero_point = quantization["zero_point"]
+ # dim = quantization['dim']
+
+ #
+ # Sometimes we get a scalar with ScaleAsNumpy.
+ # This seem to mean not quantized ?
+ #
+ if not isinstance(scale, np.ndarray):
+ assert scale == 0.0, f"Non-quantized tensor with scale != 0.0"
+ assert (
+ not isinstance(zero_point, np.ndarray) and zero_point == 0
+ ), f"Non-quantized tensor with zero_point != 0"
+ return None
+
+ scale_size = len(scale)
+ zero_point_size = len(zero_point)
+
+ assert len(scale) == len(
+ zero_point
+ ), f"Inconsistent quantizations scale:{scale} vs zero-point:{zero_point}"
+
+ if len(scale) == 1:
+ quant_name = dl_tensor_name + "_quant"
+ out_c.write(f"AI_STATIC float {quant_name}_scale[{scale_size}] = {{ ")
+ for val in scale:
+ out_c.write(f"{val}, ")
+ out_c.write(f"}};\n")
+ out_c.write(f"AI_STATIC int32_t {quant_name}_zero_point[{zero_point_size}] = {{ ")
+ for val in zero_point:
+ out_c.write(f"{val}, ")
+ out_c.write(f"}};\n")
+ out_c.write(f"AI_STATIC ai_quantization_info {quant_name} = {{\n")
+ out_c.write(f" .scale = {quant_name}_scale,\n")
+ out_c.write(f" .zero_point = {quant_name}_zero_point,\n")
+ out_c.write(f" .dim = -1\n")
+ out_c.write(f"}}; \n")
+
+ return quant_name
+
+ return None
+
+
+def emit_tensor_init(dl_tensor_name, tensor, quantization_map, out_c):
+ """Emit tensor definition."""
+ dltype = tensor["dltype"]
+ dims = tensor["dims"]
+ strides = tensor["strides"]
+ if "device" in tensor:
+ device = tensor["device"]
+ else:
+ device = "kDLCPU"
+ # storage_id = tensor['storage_id']
+ byte_offset = tensor["byte_offset"]
+ # size = tensor['size']
+ dtype = _get_type_data(dltype)
+ ndim = len(dims)
+ shape = str(dims)
+ _emit_tensor_shape(dl_tensor_name, ndim, shape, strides, out_c)
+
+ #
+ # Quantization
+ #
+ if quantization_map is not None:
+ quant_name = _emit_tensor_quant(dl_tensor_name, quantization_map, out_c)
+ else:
+ quant_name = None
+
+ #
+ # Contents
+ #
+ out_c.write(f"AI_ALIGNED({8}) AI_STATIC ai_tensor {dl_tensor_name} = {{ \n")
+ out_c.write(f" .dltensor = {{ \n")
+ out_c.write(f" .data = (ai_ptr)(NULL), \n")
+ #
+ # TODO: use the 'storage_id'
+ #
+ out_c.write(f" .device = {{ {device}, 0 }}, \n")
+ out_c.write(f" .ndim = {ndim}, \n")
+ out_c.write(f" .dtype = {{ {dtype} }}, \n")
+ out_c.write(f" .shape = {dl_tensor_name}_shape, \n")
+ if strides is not None:
+ out_c.write(f" .strides = {dl_tensor_name}_strides, \n")
+ else:
+ out_c.write(f" .strides = NULL, \n")
+ out_c.write(f" .byte_offset = {byte_offset} \n")
+ out_c.write(f" }}, \n")
+ #
+ # Figure out quantization, if exists
+ #
+ if quant_name is not None:
+ out_c.write(f" .quant = &{quant_name} \n")
+ else:
+ out_c.write(f" .quant = NULL \n")
+ out_c.write(f"}}; \n")
+
+
+class BaseEmitter:
+ """Base code emitter class."""
+
+ def __init__(
+ self, model_name, include_activations=True, include_inputs=True, include_outputs=True
+ ):
+ """Initialize the Emitter instance.
+
+ Parameters
+ ----------
+ include_activations:
+ The Emitter allocates the storage for the activations data
+ and places it in a specific data section. If Falsr, the
+ main application is responsible for allocating the activations
+ storage. Default: True.
+
+ include_inputs/include_outputs:
+ The Emitter allocates the storage for the input/output data.
+ This storage is shared with the activations and placed in the
+ specific activations data section. If False, the main
+ application is responsible for allocating the input/output
+ data storage. Default: True.
+
+ Returns
+ -------
+ CodeEmitter object.
+
+ """
+
+ #
+ # Fix the model name
+ #
+ model_name = re.sub("[^0-9a-zA-Z_]+", "_", model_name)
+ model_name = model_name.lower()
+ self.model_name_ = model_name
+
+ #
+ # Constants:
+ #
+ self.data_alignment = 8
+
+ #
+ # Static model: activations placed into a nn_data_act section
+ # Dynamic model: activations need to be malloc'ed by the
+ # applications.
+ #
+ if include_activations is True:
+ self.activations_static = 1
+ else:
+ self.activations_static = 0
+
+ #
+ # Inputs/outputs may be allocated within the activations or
+ # separately.
+ # TODO: Separate the inputs from activations inside TVM.
+ #
+ if include_inputs is True:
+ assert (
+ self.activations_static == 1
+ ), "###Error: Static inputs are not allowed without activations."
+ self.inputs_static = 1
+ else:
+ self.inputs_static = 0
+
+ if include_outputs is True:
+ assert (
+ self.activations_static == 1
+ ), "###Error: Static outputs are not allowed without activations."
+ self.outputs_static = 1
+ else:
+ self.outputs_static = 0
+
+ #
+ # Parsed graph
+ #
+ self.nodes_ = []
+ self.arg_nodes_ = []
+ self.outputs_ = []
+ self.attrs_ = {}
+ self.node_row_ptr_ = []
+ #
+ # Filled by data_placement()
+ #
+ self.weights_ = {}
+ self.activations_ = {}
+ self.input_data_ = {}
+ self.output_data_ = {}
+ self.nodes_size_ = 0
+ self.weights_size_ = 0
+ self.activations_size_ = 0
+
+ self.graph_ = None
+ self.params_ = {}
+ self.lib_ = None
+
+ def _parse_model(self):
+ """Parse the module graph. Build internal data structures."""
+
+ for key in self.graph_:
+ if key == "nodes":
+ self.nodes_ = self.graph_["nodes"]
+ elif key == "arg_nodes":
+ self.arg_nodes_ = self.graph_["arg_nodes"]
+ elif key == "node_row_ptr":
+ self.node_row_ptr_ = self.graph_["node_row_ptr"]
+ elif key == "heads":
+ self.outputs_ = self.graph_["heads"]
+ elif key == "attrs":
+ self.attrs_ = self.graph_["attrs"]
+ elif key == "metadata":
+ continue
+ else:
+ print("### Error: JSON key {} not supported".format(key))
+ assert False
+
+ def parse_library_format(self, model_library_format_path):
+ """Parse the module. Build internal data structures.
+
+ Parameters
+ ----------
+ model_name :
+ Name for this model.
+
+ model_library_format_path :
+ The module to parse
+ """
+
+ temp_dir = utils.tempdir()
+ extract_path = temp_dir.relpath("extract")
+ os.mkdir(extract_path)
+ with tarfile.TarFile(model_library_format_path) as f:
+ f.extractall(extract_path)
+
+ #
+ # Extract informations from the Model Library Format
+ #
+ graph_file = os.path.join(extract_path, "runtime-config", "graph", "graph.json")
+ with open(graph_file, "r") as f:
+ # returns JSON object as a dictionary
+ graph_dict = json.load(f)
+
+ param_file = os.path.join(extract_path, "parameters", "default.params")
+ with open(param_file, "rb") as f:
+ params = tvm.runtime.load_param_dict(f.read())
+ #
+ # Map -> Python Dict
+ #
+ tmp_dict = {}
+ for (k, v) in params.items():
+ tmp_dict[k] = v
+
+ #
+ # Sort params for debugging
+ #
+ for k in sorted(tmp_dict.keys()):
+ self.params_[k] = tmp_dict[k]
+
+ src_dir = os.path.join(extract_path, "codegen", "host", "src")
+ # List of strings from Model Library Format C files
+ src_files = []
+ for filename in os.listdir(src_dir):
+ with open(os.path.join(src_dir, filename), "r") as fin:
+ src = fin.read()
+ src_files.append(src)
+
+ self.graph_ = graph_dict
+ self.lib_ = src_files
+
+ self._parse_model()
+
+ def parse_model(self, module):
+ """Parse the module. Build internal data structures.
+
+ Parameters
+ ----------
+ model_name :
+ Name for this model.
+
+ module : TVM module
+ The module to parse
+ """
+
+ graph = module.get_json()
+ if not isinstance(graph, (str,)):
+ try:
+ graph = graph._tvm_graph_json()
+ except AttributeError:
+ raise ValueError("Type %s is not supported" % type(graph))
+
+ #
+ # Sort params for debugging
+ #
+ tmp_params = module.get_params()
+ for k in sorted(tmp_params.keys()):
+ self.params_[k] = tmp_params[k]
+
+ self.graph_ = json.loads(graph)
+ self.lib_ = module.get_lib()
+
+ self._parse_model()
+
+ def _tensor_is_output(self, nid, idx):
+
+ for out in self.outputs_:
+ out_nid = out[0]
+ out_idx = out[1]
+ if out_nid == nid and out_idx == idx:
+ return True
+ return False
+
+ def _get_tensor_from_node(self, nid, idx):
+ #
+ # 'eid' is index into the dltype', 'shape', etc.
+ #
+ eid = self.node_row_ptr_[nid] + idx
+
+ dltype = self.attrs_["dltype"][1][eid]
+ dims = self.attrs_["shape"][1][eid]
+ storage_id = self.attrs_["storage_id"][1][eid]
+ ndim = len(dims)
+ size = get_tensor_size(dims, dltype)
+ tensor = {
+ "dltype": dltype,
+ "ndim": ndim,
+ "dims": dims,
+ "strides": None,
+ "storage_id": storage_id,
+ "byte_offset": 0,
+ "offset": 0,
+ "size": size,
+ }
+
+ return tensor
+
+ def _get_node_input_name(self, arg):
+ arg_nid = arg[0]
+ arg_idx = arg[1]
+ arg_node = self.nodes_[arg_nid]
+ arg_name = self.nodes_[arg_nid]["name"]
+ if arg_node["op"] == "null":
+ # parameter
+ dl_tensor_name = get_input_tensor_name(arg_name)
+ elif arg_node["name"] == "reshape_nop":
+ # Handle __nop
+ src = arg_node["inputs"][0]
+ dl_tensor_name = self._get_node_input_name(src)
+ else:
+ # activation
+ dl_tensor_name = get_output_tensor_name(arg_name, arg_idx)
+ return dl_tensor_name
+
+ def compute_data_placement(self):
+ """Compute inputs, outputs, weight, activation sizes."""
+
+ self.inputs_ = self.arg_nodes_.copy()
+
+ #
+ # weights:
+ #
+ offset = 0
+
+ #
+ # Order is important := the order of how the weights will be
+ # written to memory.
+ #
+ for key in self.params_:
+ #
+ # First, find the node in graph
+ #
+ nid = 0
+ for node in self.nodes_:
+ if node["name"] == key:
+ break
+ nid += 1
+
+ #
+ # May not find
+ #
+ if nid == len(self.nodes_):
+ continue
+
+ dl_tensor_name = get_input_tensor_name(key)
+ tensor = self._get_tensor_from_node(nid, 0)
+ #
+ # Compute the offset
+ #
+ dltype = tensor["dltype"]
+ aligned_offset = get_aligned_offset(offset, dltype)
+ tensor["offset"] = aligned_offset
+
+ for idx in self.arg_nodes_:
+ node = self.nodes_[idx]
+ node_name = node["name"]
+ if node_name == key:
+ self.inputs_.remove(idx)
+
+ self.weights_[dl_tensor_name] = tensor
+
+ #
+ # Next offset
+ #
+ offset = aligned_offset + tensor["size"]
+
+ self.weights_size_ = offset
+
+ #
+ # activations:
+ #
+
+ buffer_list_ = {}
+
+ nid = 0
+
+ for node in self.nodes_:
+
+ if node["op"] == "null":
+ nid += 1
+ continue
+
+ if node["op"] != "tvm_op":
+ raise ValueError(f"Only TVM ops are supported")
+
+ node_name = node["name"]
+ node_attrs = node["attrs"]
+ func_name = node_attrs["func_name"]
+ num_outputs = int(node_attrs["num_outputs"])
+
+ if func_name == "__nop":
+ assert node_name == "reshape_nop", f"Unsupported __nop operator {node_name}."
+ assert num_outputs == 1
+ assert not self._tensor_is_output(nid, 0)
+ nid += 1
+ continue
+
+ for idx in range(num_outputs):
+ #
+ # Do not count the 'outputs_'
+ #
+ if self._tensor_is_output(nid, idx):
+ continue
+
+ dl_tensor_name = get_output_tensor_name(node_name, idx)
+ tensor = self._get_tensor_from_node(nid, idx)
+ #
+ # Remember this tensor with the storage id
+ #
+ storage_id = tensor["storage_id"]
+ if storage_id not in buffer_list_:
+ buffer_list_[storage_id] = []
+ buffer_entry = buffer_list_[storage_id]
+ buffer_entry.append(tensor)
+
+ self.activations_[dl_tensor_name] = tensor
+
+ self.nodes_size_ = self.nodes_size_ + 1
+
+ nid += 1
+
+ #
+ # Compute 'input_data_'
+ #
+ offset = 0
+
+ for nid in self.inputs_:
+ node = self.nodes_[nid]
+ node_name = node["name"]
+ #
+ # Arthur: I suppose that input nodes only have a single
+ # output dependency
+ #
+ dl_tensor_name = get_input_tensor_name(node_name)
+ #
+ # This tensor is at some index inside 'input_data_' dictionary
+ # depending on the 'inputs_' list order. We refer to this position
+ # when generating the XXX.h file.
+ #
+ tensor = self._get_tensor_from_node(nid, 0)
+
+ if self.inputs_static == 1:
+ #
+ # Remember this tensor with the storage id
+ #
+ storage_id = tensor["storage_id"]
+ if storage_id not in buffer_list_:
+ buffer_list_[storage_id] = []
+ buffer_entry = buffer_list_[storage_id]
+ buffer_entry.append(tensor)
+ else:
+ #
+ # Compute the offset
+ #
+ dltype = tensor["dltype"]
+ aligned_offset = get_aligned_offset(offset, dltype)
+ tensor["offset"] = aligned_offset
+ #
+ # Next offset
+ #
+ offset = aligned_offset + tensor["size"]
+
+ self.input_data_[dl_tensor_name] = tensor
+
+ #
+ # Compute 'output_data_'
+ #
+ offset = 0
+
+ for output in self.outputs_:
+
+ nid = output[0]
+ idx = output[1]
+
+ node = self.nodes_[nid]
+ node_name = node["name"]
+
+ dl_tensor_name = get_output_tensor_name(node_name, idx)
+
+ tensor = self._get_tensor_from_node(nid, idx)
+
+ if self.outputs_static == 1:
+ #
+ # Remember this tensor with the storage id
+ #
+ storage_id = tensor["storage_id"]
+ if storage_id not in buffer_list_:
+ buffer_list_[storage_id] = []
+ buffer_entry = buffer_list_[storage_id]
+ buffer_entry.append(tensor)
+ else:
+ #
+ # Compute the offset
+ #
+ dltype = tensor["dltype"]
+ aligned_offset = get_aligned_offset(offset, dltype)
+ tensor["offset"] = aligned_offset
+ #
+ # Next offset
+ #
+ offset = aligned_offset + tensor["size"]
+
+ self.output_data_[dl_tensor_name] = tensor
+
+ #
+ # Go over all storage IDs and compute offsets and activations_size_
+ #
+ offset = 0
+
+ for storage_id in buffer_list_:
+ buffer_entry = buffer_list_[storage_id]
+
+ new_offset = offset
+ for tensor in buffer_entry:
+ assert tensor["storage_id"] == storage_id
+ dltype = tensor["dltype"]
+ aligned_offset = get_aligned_offset(offset, dltype)
+ tensor["offset"] = aligned_offset
+ size = tensor["size"]
+ if (aligned_offset + size) > new_offset:
+ new_offset = aligned_offset + size
+ offset = new_offset
+
+ self.activations_size_ = offset
+
+ def _emit_tensor_activation(self, dl_tensor_name, tensor, out_c):
+
+ storage_id = tensor["storage_id"]
+ offset = tensor["offset"]
+ out_c.write(f" // \n")
+ out_c.write(f" // {dl_tensor_name}: storage_id:{storage_id}\n")
+ out_c.write(f" // \n")
+ out_c.write(f" {dl_tensor_name}.dltensor.data = (ai_ptr)(activations + {offset}); \n")
+ out_c.write(f"\n")
+
+ def _emit_activation_init(self, name, out_c):
+ """Emits buffer initialization code for activation tensors."""
+ out_c.write(f"// {DBAR} \n")
+ out_c.write(f"// {name}_configure_activations \n")
+ out_c.write(f"// {DBAR} \n")
+ out_c.write(f"AI_STATIC AI_INLINE\n")
+ out_c.write(f"ai_status {name}_configure_activations ( \n")
+ out_c.write(f" const ai_ptr activations \n")
+ out_c.write(f") \n")
+ out_c.write(f"{{ \n")
+ out_c.write(f" if (activations == NULL) {{\n")
+ out_c.write(
+ f' TVMAPISetLastError ("Non-null activations arena is required for this model.");\n'
+ )
+ out_c.write(f" return AI_STATUS_ERROR;\n")
+ out_c.write(f" }}\n")
+ out_c.write(f"\n")
+
+ #
+ # Allocate inputs with the static model
+ #
+ if self.inputs_static:
+ for dl_tensor_name in self.input_data_:
+ tensor = self.input_data_[dl_tensor_name]
+ self._emit_tensor_activation(dl_tensor_name, tensor, out_c)
+
+ #
+ # Prepare activation buffers
+ #
+ for dl_tensor_name in self.activations_:
+ tensor = self.activations_[dl_tensor_name]
+ self._emit_tensor_activation(dl_tensor_name, tensor, out_c)
+
+ #
+ # Allocate outputs with the static model
+ #
+ if self.outputs_static:
+ for dl_tensor_name in self.output_data_:
+ tensor = self.output_data_[dl_tensor_name]
+ self._emit_tensor_activation(dl_tensor_name, tensor, out_c)
+
+ out_c.write(f" return AI_STATUS_OK; \n")
+ out_c.write(f"}} \n")
+ out_c.write(f"\n")
+
+ def _emit_params_init(self, name, out_c):
+ """Emits buffer initialization code for params tensors."""
+ out_c.write(f"// {DBAR} \n")
+ out_c.write(f"// {name}_configure_weights \n")
+ out_c.write(f"// {DBAR} \n")
+ out_c.write(f"AI_STATIC AI_INLINE\n")
+ out_c.write(f"ai_status {name}_configure_weights ( \n")
+ out_c.write(f" const ai_ptr weights \n")
+ out_c.write(f") \n")
+ out_c.write(f"{{ \n")
+ out_c.write(f" if (weights == NULL) {{\n")
+ out_c.write(
+ f' TVMAPISetLastError ("Non-null weights arena is required for this model.");\n'
+ )
+ out_c.write(f" return AI_STATUS_ERROR;\n")
+ out_c.write(f" }}\n")
+ out_c.write(f"\n")
+
+ for dl_tensor_name in self.weights_:
+ tensor = self.weights_[dl_tensor_name]
+ offset = tensor["offset"]
+ out_c.write(f" // \n")
+ out_c.write(f" // {dl_tensor_name}\n")
+ out_c.write(f" // \n")
+ out_c.write(f" {dl_tensor_name}.dltensor.data = (ai_ptr)(weights + {offset}); \n")
+ out_c.write(f"\n")
+
+ out_c.write(f" return AI_STATUS_OK; \n")
+ out_c.write(f"}} \n")
+ out_c.write(f"\n")
+
+ def emit_init(self, out_c):
+ """Emits buffer initialization code."""
+ #
+ # {name}_configure_activations
+ #
+ self._emit_activation_init(self.model_name_, out_c)
+ #
+ # {name}_configure_weights
+ #
+ self._emit_params_init(self.model_name_, out_c)
+
+ def emit_operator_proto(self, node, out_c):
+ """Emit operator C prototype."""
+
+ node_attrs = node["attrs"]
+ func_name = node_attrs["func_name"]
+
+ if func_name == "__nop":
+ return
+
+ if func_name == "__copy":
+ return
+
+ out_c.write(
+ f"TVM_DLL int32_t {func_name}(void * args, void * arg_type_ids, int32_t num_args); \n"
+ )
+
+ def emit_operator_call(self, node, out_c):
+ """Emit operator code at call site."""
+
+ node_name = node["name"]
+ node_attrs = node["attrs"]
+ func_name = node_attrs["func_name"]
+
+ if func_name == "__nop":
+ return
+
+ if func_name == "__copy":
+ return
+
+ out_c.write(f" // \n")
+ out_c.write(f" // {func_name}\n")
+ out_c.write(f" // \n")
+
+ #
+ # Prepare TVM packed function - this is the one called
+ #
+
+ #
+ # Get function from the TVM module
+ #
+ # void * args : arg_values.data()
+ # void * arg_type_ids : arg_tcodes.data()
+ # int32_t num_args : arg_values.size()
+ #
+
+ node_name_upper = node_name.upper()
+ dl_args_name = get_node_args_name(node_name)
+ dl_arg_types_name = get_node_arg_types_name(node_name)
+
+ num_inputs = len(node["inputs"])
+ num_outputs = int(node_attrs["num_outputs"])
+ num_args = num_inputs + num_outputs
+
+ out_c.write(f" TVMValue {dl_args_name}[{num_args}]; \n")
+ out_c.write(f" int32_t {dl_arg_types_name}[{num_args}]; \n")
+
+ curr_idx = 0
+
+ for arg in node["inputs"]:
+ dl_tensor_name = self._get_node_input_name(arg)
+ #
+ # If this input is not an activation or a parameter => find the input
+ #
+ if dl_tensor_name not in self.weights_ and dl_tensor_name not in self.activations_:
+ assert (
+ dl_tensor_name in self.input_data_
+ ), f"Tensor {dl_tensor_name} not registered ?"
+ input_idx = 0
+ for dl_entry_name in self.input_data_:
+ if dl_entry_name == dl_tensor_name:
+ break
+ input_idx += 1
+ out_c.write(
+ f" {dl_args_name}[{curr_idx}].v_handle = &inputs[{input_idx}]->dltensor; \n"
+ )
+ else:
+ out_c.write(
+ f" {dl_args_name}[{curr_idx}].v_handle = &{dl_tensor_name}.dltensor; \n"
+ )
+ out_c.write(f" {dl_arg_types_name}[{curr_idx}] = kTVMNDArrayHandle; \n")
+ if dl_tensor_name in self.weights_:
+ out_c.write(f"#ifdef _DUMP_INPUTS_ \n")
+ out_c.write(
+ f' TVMDumpBuffer ("{dl_tensor_name}", &{dl_tensor_name}, DumpFile_p); \n'
+ )
+ out_c.write(f"#endif \n")
+ elif dl_tensor_name in self.input_data_:
+ input_idx = 0
+ for dl_entry_name in self.input_data_:
+ if dl_entry_name == dl_tensor_name:
+ break
+ input_idx += 1
+ out_c.write(f"#ifdef _DUMP_INPUTS_ \n")
+ out_c.write(
+ f' TVMDumpBuffer ("{dl_tensor_name}", inputs[{input_idx}], DumpFile_p); \n'
+ )
+ out_c.write(f"#endif \n")
+
+ out_c.write(f"\n")
+
+ curr_idx += 1
+
+ for idx in range(num_outputs):
+ dl_tensor_name = get_output_tensor_name(node_name, idx)
+ #
+ # If this output is not an activation => find the output
+ #
+ if dl_tensor_name not in self.activations_:
+
+ assert dl_tensor_name in self.output_data_
+
+ output_idx = 0
+ for dl_exit_name in self.output_data_:
+ if dl_exit_name == dl_tensor_name:
+ break
+ output_idx += 1
+ out_c.write(
+ f" {dl_args_name}[{curr_idx}].v_handle = &outputs[{output_idx}]->dltensor; \n"
+ )
+ else:
+ out_c.write(
+ f" {dl_args_name}[{curr_idx}].v_handle = &{dl_tensor_name}.dltensor; \n"
+ )
+ out_c.write(f" {dl_arg_types_name}[{curr_idx}] = kTVMNDArrayHandle; \n")
+ out_c.write(f"\n")
+
+ curr_idx += 1
+
+ #
+ # call this function
+ #
+ out_c.write(f"#if (_VERBOSE_ > 0) \n")
+ out_c.write(f' printf (" {func_name} ... \\r\\n"); \n')
+ out_c.write(f"#endif \n")
+
+ out_c.write(f" if ({func_name} ({dl_args_name}, {dl_arg_types_name}, {num_args})) {{ \n")
+ out_c.write(f' TVMAPISetLastError("Invalid handle");\n')
+ out_c.write(f" return AI_STATUS_ERROR; \n")
+
+ out_c.write(f" }} \n")
+ out_c.write(f"#if (_VERBOSE_ > 0) \n")
+ out_c.write(f' printf (" {func_name} Done.\\r\\n"); \n')
+ out_c.write(f"#endif \n")
+ out_c.write(f"\n")
+
+ out_c.write(f"#ifdef _DUMP_{node_name_upper}_ \n")
+ for idx in range(num_outputs):
+ dl_tensor_name = get_output_tensor_name(node_name, idx)
+ if dl_tensor_name in self.activations_:
+ out_c.write(
+ f' TVMDumpBuffer ("{dl_tensor_name}", &{dl_tensor_name}, DumpFile_p); \n'
+ )
+ else:
+ assert dl_tensor_name in self.output_data_
+ output_idx = 0
+ for dl_exit_name in self.output_data_:
+ if dl_exit_name == dl_tensor_name:
+ break
+ output_idx += 1
+ out_c.write(
+ f' TVMDumpBuffer ("{dl_tensor_name}", outputs[{output_idx}], DumpFile_p); \n'
+ )
+
+ out_c.write(f"#endif \n")
+
+ def emit_params_data(self, target_dir):
+ """Emits the network_data[c,h] files with parameters."""
+ name = self.model_name_
+ name_upper = self.model_name_.upper()
+
+ data_h_name = os.path.join(target_dir, name + "_data.h")
+ data_c_name = os.path.join(target_dir, name + "_data.c")
+
+ out_h = open(data_h_name, "w")
+ out_c = open(data_c_name, "w")
+
+ #
+ # XXX_data.h
+ #
+ out_h.write(f"#ifndef __{name_upper}_DATA_H_ \n")
+ out_h.write(f"#define __{name_upper}_DATA_H_ \n")
+ out_h.write(f"\n")
+ out_h.write(f'#include "ai_runtime_api.h" \n')
+ out_h.write(f"\n")
+
+ out_h.write(f"AI_API_ENTRY \n")
+ out_h.write(f"const ai_ptr ai_{name}_data_weights_get (void); \n")
+ out_h.write(f"\n")
+
+ out_h.write(f"#endif /* __{name_upper}_DATA_H_ */ \n")
+ out_h.write(f"\n")
+
+ #
+ # XXX_data.cc
+ #
+ out_c.write(f'#include "{name}_data.h" \n')
+ out_c.write(f"\n")
+
+ out_c.write(f"const ai_ptr ai_{name}_data_weights_get (void) \n")
+ out_c.write(f"{{\n")
+ out_c.write(
+ f' AI_ALIGNED(4) static const __attribute__ ((section(".nn_weights"))) uint8_t s_{name}_weights[] = {{ \n'
+ )
+
+ offset = 0
+ for key in self.params_:
+ data = self.params_[key] # ND Array
+ npdata = data.asnumpy()
+ blob = npdata.tobytes()
+
+ out_c.write(f'// "{key}": \n')
+ out_c.write(f"\t")
+
+ count = 0
+
+ #
+ # Align by emitting garbage between un-aligned data
+ #
+ dl_tensor_name = get_input_tensor_name(key)
+ tensor = self.weights_[dl_tensor_name]
+ tensor_offset = tensor["offset"]
+ tensor_size = tensor["size"]
+
+ while offset < tensor_offset:
+ count += 1
+ out_c.write("0x{:02X}, ".format(0))
+ if count == 12:
+ out_c.write("\n\t")
+ count = 0
+ offset += 1
+
+ for val in blob:
+ count += 1
+ out_c.write("0x{:02X}, ".format(val))
+ if count == 12:
+ out_c.write("\n\t")
+ count = 0
+
+ offset += tensor_size
+
+ out_c.write(f"\n")
+
+ out_c.write(f" }}; \n")
+ out_c.write(f" return (const ai_ptr)s_{name}_weights; \n")
+ out_c.write(f"}} \n")
+ out_c.write(f"\n")
+
+ out_h.close()
+ out_c.close()
+
+ def emit_open(self, out_h, out_c):
+ """Emits the network.h file with a few network defines and
+ writes the header part of the network.c file."""
+
+ name = self.model_name_
+ name_upper = name.upper()
+
+ #
+ # XXX.h
+ #
+ out_h.write(f"#ifndef __AI_{name_upper}_H__ \n")
+ out_h.write(f"#define __AI_{name_upper}_H__ \n")
+ out_h.write(f"\n")
+
+ out_h.write(f'#include "ai_runtime_api.h" \n')
+ out_h.write(f"\n")
+
+ input_size = len(self.input_data_)
+ output_size = len(self.output_data_)
+ out_h.write(f"#define _{name_upper}_INPUTS_COUNT_ ({input_size})\n")
+ out_h.write(f"#define _{name_upper}_OUTPUTS_COUNT_ ({output_size})\n")
+ out_h.write(f"#define _{name_upper}_ACTIVATION_BYTES_ ({self.activations_size_})\n")
+ out_h.write(f"\n")
+
+ #
+ # XXX.c
+ #
+ out_c.write(f"#include <stdio.h> \n")
+ out_c.write(f"\n")
+
+ out_c.write(f'#include "dlpack/dlpack.h" \n')
+ # out_c.write(f'#include "tvm/runtime/c_runtime_api.h" \n')
+ out_c.write(f'#include "tvm/runtime/c_backend_api.h" \n')
+ out_c.write(f'#include "{name}.h" \n')
+ out_c.write(f'#include "{name}_data.h" \n')
+ out_c.write(f"\n")
+
+ def emit_close(self, out_h, out_c):
+ """Emits the ai_model_info structure."""
+
+ name = self.model_name_
+ name_upper = name.upper()
+
+ # datetime object containing current date and time
+ now = datetime.now()
+ # dd/mm/YY H:M:S
+ dt_string = now.strftime("%d/%m/%Y %H:%M:%S")
+
+ #
+ # XXX.h
+ #
+ out_h.write(f"#endif /*__AI_{name_upper}_H__*/ \n")
+
+ #
+ # XXX.c
+ #
+
+ #
+ # Emit network structure
+ #
+ num_inputs = len(self.input_data_)
+ num_outputs = len(self.output_data_)
+
+ out_c.write(
+ f'AI_API_ENTRY __attribute__ ((section(".nn_models"))) ai_model_info {name}_network = {{\n'
+ )
+ out_c.write(f' .name = "{name}",\n')
+ out_c.write(f' .datetime = "{dt_string}",\n')
+ out_c.write(f' .revision = "{AI_TOOLS_REVISION}",\n')
+ out_c.write(
+ f' .tool_version = "{AI_TOOLS_VERSION_MAJOR}.{AI_TOOLS_VERSION_MINOR}.{AI_TOOLS_VERSION_MICRO}.0",\n'
+ )
+ out_c.write(
+ f' .api_version = "{AI_API_VERSION_MAJOR}.{AI_API_VERSION_MINOR}.{AI_API_VERSION_MICRO}.0",\n'
Review comment:
since the python emitter is writing code to meet this version, does it makes sense to hardcode the version string here rather than in a header file which may not match the Python at time of compilation?
##########
File path: src/runtime/crt/contrib/stm32/ai_runtime_api.h
##########
@@ -0,0 +1,226 @@
+/*
+ * 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.
+ */
+
+/*!
+ * \file ai_runtime_api.h
+ * \brief The runtime API for the TVM generated C code.
+ */
+
+#ifndef TVM_RUNTIME_CRT_CONTRIB_STM32_AI_RUNTIME_API_H_
+#define TVM_RUNTIME_CRT_CONTRIB_STM32_AI_RUNTIME_API_H_
+
+#include "ai_platform.h"
+#include "dlpack/dlpack.h" // From TVM
+#include "tvm/runtime/c_runtime_api.h" // From TVM
+
+//
+// This describes current ai_runtime version
+//
+#define AI_PLATFORM_RUNTIME_MAJOR 1
+#define AI_PLATFORM_RUNTIME_MINOR 0
+#define AI_PLATFORM_RUNTIME_MICRO 0
+
+#define AI_STATIC static
+
+#if defined(_MSC_VER)
+#define AI_INLINE __inline
+#elif defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
+#define AI_INLINE inline
+#elif defined(__CC_ARM)
+#define AI_INLINE __inline
+/* Keil disallows anonymous union initialization by default */
+#pragma anon_unions
+#elif defined(__GNUC__)
+#define AI_INLINE __inline
+#else
+/* Dynamic libraries are not supported by the compiler */
+#endif
+
+/*********************************************************/
+
+typedef uint8_t* ai_ptr;
+
+typedef enum { AI_STATUS_OK = 0, AI_STATUS_ERROR = 1, AI_STATUS_DELEGATE_ERROR = 2 } ai_status;
+
+// =======================================================
+// ai_quantization_info
+//
+// Parameters for asymmetric quantization across a dimension (i.e
+// per output channel quantization).
+// quantized_dimension specifies which dimension the scales and
+// zero_points correspond to.
+// For a particular value in quantized_dimension, quantized values
+// can be converted back to float using:
+// real_value = scale * (quantized_value - zero_point)
+// =======================================================
+
+typedef struct {
+ /*!
+ * \brief The quantization info, if quantized
+ */
+ float* scale;
+ int32_t* zero_point;
+ int32_t dim;
+} ai_quantization_info;
+
+// =======================================================
+// ai_tensor
+// =======================================================
+
+typedef struct {
+ /*!
+ * \brief The TVM tensor.
+ */
+ DLTensor dltensor;
+ /*!
+ * \brief The quantization info, if quantized
+ */
+ ai_quantization_info* quant;
+} ai_tensor;
+
+// =======================================================
+// get_dltensor
+// =======================================================
+AI_STATIC AI_INLINE DLTensor* get_dltensor(ai_tensor* tensor) { return &tensor->dltensor; }
+
+// =======================================================
+// get_tensor_elts
+// =======================================================
+AI_STATIC AI_INLINE uint32_t get_tensor_elts(const ai_tensor* tensor) {
+ const DLTensor* t = &tensor->dltensor;
+ uint32_t elts = 1;
+ for (int i = 0; i < t->ndim; ++i) {
+ elts *= t->shape[i];
+ }
+ return elts;
+}
+
+// =======================================================
+// get_tensor_size
+// =======================================================
+AI_STATIC AI_INLINE uint32_t get_tensor_size(const ai_tensor* tensor) {
+ const DLTensor* t = &tensor->dltensor;
+ uint32_t size = 1;
+ for (int i = 0; i < t->ndim; ++i) {
+ size *= t->shape[i];
+ }
+ size *= (t->dtype.bits * t->dtype.lanes + 7) / 8;
+ return size;
+}
+
+// =======================================================
+// ai_network_info
+// =======================================================
+
+typedef struct {
+ const char* name;
+ const char* datetime;
+ const char* revision;
+ const char* tool_version;
+ const char* api_version;
+ uint16_t n_nodes;
+ uint8_t n_inputs;
+ uint8_t n_outputs;
+ uint32_t activations_size;
+ uint32_t params_size;
+ ai_ptr activations;
+ ai_tensor** inputs;
+ ai_tensor** outputs;
+ const ai_ptr (*ai_get_params)(void);
+ ai_status (*ai_create)(const ai_ptr weights, const ai_ptr activations);
+ ai_status (*ai_destroy)();
+ ai_status (*ai_run)(ai_tensor* input[], ai_tensor* output[]);
+} ai_model_info;
+
+#define AI_MODEL_name(x) (x->name)
+#define AI_MODEL_datetime(x) (x->datetime)
+#define AI_MODEL_revision(x) (x->revision)
+#define AI_MODEL_tool_version(x) (x->tool_version)
+#define AI_MODEL_api_version(x) (x->api_version)
+#define AI_MODEL_n_nodes(x) (x->n_nodes)
+#define AI_MODEL_n_inputs(x) (x->n_inputs)
+#define AI_MODEL_n_outputs(x) (x->n_outputs)
+#define AI_MODEL_activations_size(x) (x->activations_size)
+#define AI_MODEL_params_size(x) (x->params_size)
+#define AI_MODEL_inputs(x) (x->inputs)
+#define AI_MODEL_outputs(x) (x->outputs)
+#define AI_MODEL_activations(x) (x->activations)
+
+// =======================================================
+// Iterator
+//
+// Usage:
+//
+// for (ai_models_iterator it = ai_models_iterator_begin();
+// it != ai_models_iterator_end();
+// it = ai_models_iterator_next(it)) {
+// const char * name = ai_models_iterator_value(it);
+// }
+//
+// =======================================================
+
+typedef uint32_t ai_model_iterator;
+
+ai_model_iterator ai_model_iterator_begin();
+ai_model_iterator ai_model_iterator_next(ai_model_iterator it);
+ai_model_iterator ai_model_iterator_end();
+ai_model_info* ai_model_iterator_value(ai_model_iterator it);
+
+// =======================================================
+// External Interface
+// =======================================================
+
+ai_status ai_create(ai_model_info* nn, void* context, ai_handle* handle);
+
+ai_status ai_destroy(ai_handle handle);
+
+const char* ai_get_error(ai_handle handle);
+
+int32_t ai_get_input_size(ai_handle handle);
+
+int32_t ai_get_output_size(ai_handle handle);
+
+ai_tensor* ai_get_input(ai_handle handle, int32_t index);
+
+ai_tensor* ai_get_output(ai_handle handle, int32_t index);
+
+ai_status ai_run(ai_handle handle);
+
+//
+// Additional methods
+//
+const char* ai_get_name(ai_handle handle);
Review comment:
could you ensure these are tested? in particular i only see usages of name, get_activations, and get_params in the tests
##########
File path: src/runtime/crt/contrib/stm32/ai_platform.h
##########
@@ -0,0 +1,383 @@
+/*
+ * 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.
+ */
+
+/*!
+ * \file ai_platform.h
+ * \brief Definitions of AI platform public APIs types
+ */
+
+// LINT_C_FILE
+
+#ifndef AI_PLATFORM_H
+#define AI_PLATFORM_H
+#pragma once
+
+#include <inttypes.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#ifndef AI_PLATFORM_API_MAJOR
+#define AI_PLATFORM_API_MAJOR (0)
+#endif
+#ifndef AI_PLATFORM_API_MINOR
+#define AI_PLATFORM_API_MINOR (6)
+#endif
+#ifndef AI_PLATFORM_API_MICRO
+#define AI_PLATFORM_API_MICRO (0)
+#endif
+
+#define AI_PLATFORM_API_VERSION \
+ AI_VERSION(AI_PLATFORM_API_MAJOR, AI_PLATFORM_API_MINOR, AI_PLATFORM_API_MICRO)
+
+#ifndef AI_TOOLS_API_VERSION_MAJOR
+#define AI_TOOLS_API_VERSION_MAJOR (1)
+#endif
+#ifndef AI_TOOLS_API_VERSION_MINOR
+#define AI_TOOLS_API_VERSION_MINOR (4)
+#endif
+#ifndef AI_TOOLS_API_VERSION_MICRO
+#define AI_TOOLS_API_VERSION_MICRO (0)
+#endif
+
+#define AI_TOOLS_API_VERSION \
+ AI_VERSION(AI_TOOLS_API_VERSION_MAJOR, AI_TOOLS_API_VERSION_MINOR, AI_TOOLS_API_VERSION_MICRO)
+
+#define AI_TOOLS_API_VERSION_1_3 AI_VERSION(1, 3, 0)
+
+/******************************************************************************/
+#ifdef __cplusplus
+#define AI_API_DECLARE_BEGIN extern "C" {
+#define AI_API_DECLARE_END }
+#else
+#include <stdbool.h>
+#define AI_API_DECLARE_BEGIN /* AI_API_DECLARE_BEGIN */
+#define AI_API_DECLARE_END /* AI_API_DECLARE_END */
+#endif
+
+/******************************************************************************/
+#if defined(_MSC_VER)
+#define AI_API_ENTRY __declspec(dllexport)
+#define AI_ALIGNED(x) /* AI_ALIGNED(x) */
+#elif defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
+#define AI_API_ENTRY /* AI_API_ENTRY */
+#define AI_ALIGNED(x) AI_CONCAT(AI_ALIGNED_, x)
+#define AI_ALIGNED_1 _Pragma("data_alignment = 1")
+#define AI_ALIGNED_2 _Pragma("data_alignment = 2")
+#define AI_ALIGNED_4 _Pragma("data_alignment = 4")
+#define AI_ALIGNED_8 _Pragma("data_alignment = 8")
+#define AI_ALIGNED_16 _Pragma("data_alignment = 16")
+#define AI_ALIGNED_32 _Pragma("data_alignment = 32")
+#elif defined(__CC_ARM)
+#define AI_API_ENTRY __attribute__((visibility("default")))
+#define AI_ALIGNED(x) __attribute__((aligned(x)))
+/* Keil disallows anonymous union initialization by default */
+#pragma anon_unions
+#elif defined(__GNUC__)
+#define AI_API_ENTRY __attribute__((visibility("default")))
+#define AI_ALIGNED(x) __attribute__((aligned(x)))
+#else
+/* Dynamic libraries are not supported by the compiler */
+#define AI_API_ENTRY /* AI_API_ENTRY */
+#define AI_ALIGNED(x) /* AI_ALIGNED(x) */
+#endif
+
+#define AI_HANDLE_PTR(ptr_) ((ai_handle)(ptr_))
+#define AI_HANDLE_NULL AI_HANDLE_PTR(NULL)
+
+#define AI_HANDLE_FUNC_PTR(func) ((ai_handle_func)(func))
+
+#define AI_NETWORK_PARAMS_INIT(params_, activations_) \
+ { .params = params_, .activations = activations_ }
+
+/*! ai_intq_info struct handlers **********************************************/
+#define INTQ_CONST const
+// #define INTQ_CONST
+
+#define AI_INTQ_INFO_LIST(list_) ((list_)->info)
+
+#define AI_INTQ_INFO_LIST_FLAGS(list_) ((list_) ? (list_)->flags : 0)
+
+#define AI_INTQ_INFO_LIST_SIZE(list_) ((list_) ? (list_)->size : 0)
+
+#define AI_HAS_INTQ_INFO_LIST(list_) ((list_) ? (((list_)->info) && ((list_)->size > 0)) : false)
+
+#define AI_INTQ_INFO_LIST_SCALE(list_, type_, pos_) \
+ (((list_) && (list_)->info && ((pos_) < (list_)->size)) \
+ ? ((type_*)((list_)->info->scale))[(pos_)] \
+ : 0)
+
+#define AI_INTQ_INFO_LIST_ZEROPOINT(list_, type_, pos_) \
+ (((list_) && (list_)->info && ((pos_) < (list_)->size)) \
+ ? ((type_*)((list_)->info->zeropoint))[(pos_)] \
+ : 0)
+
+/*! ai_buffer format handlers *************************************************/
+
+/*!
+ * @enum buffer format definition
+ * @ingroup ai_platform
+ *
+ * 32 bit signed format list.
+ */
+typedef int32_t ai_buffer_format;
+
+/*! ai_buffer_meta flags ******************************************************/
+#define AI_BUFFER_META_HAS_INTQ_INFO (0x1U << 0)
+#define AI_BUFFER_META_FLAG_SCALE_FLOAT (0x1U << 0)
+#define AI_BUFFER_META_FLAG_ZEROPOINT_U8 (0x1U << 1)
+#define AI_BUFFER_META_FLAG_ZEROPOINT_S8 (0x1U << 2)
+
+/*! ai_buffer format variable flags *******************************************/
+#define AI_BUFFER_FMT_TYPE_NONE (0x0)
+#define AI_BUFFER_FMT_TYPE_FLOAT (0x1)
+#define AI_BUFFER_FMT_TYPE_Q (0x2)
+#define AI_BUFFER_FMT_TYPE_BOOL (0x3)
+
+#define AI_BUFFER_FMT_FLAG_CONST (0x1U << 30)
+#define AI_BUFFER_FMT_FLAG_STATIC (0x1U << 29)
+#define AI_BUFFER_FMT_FLAG_IS_IO (0x1U << 27)
+
+#define AI_BUFFER_FMT_PACK(value_, mask_, bits_) (((value_) & (mask_)) << (bits_))
+
+#define AI_BUFFER_FMT_UNPACK(fmt_, mask_, bits_) ((AI_BUFFER_FMT_OBJ(fmt_) >> (bits_)) & (mask_))
+
+#define AI_BUFFER_FMT_OBJ(fmt_) ((ai_buffer_format)(fmt_))
+
+#define AI_BUFFER_FMT_GET_FLOAT(fmt_) AI_BUFFER_FMT_UNPACK(fmt_, 0x1, 24)
+
+#define AI_BUFFER_FMT_GET_SIGN(fmt_) AI_BUFFER_FMT_UNPACK(fmt_, 0x1, 23)
+
+#define AI_BUFFER_FMT_GET_TYPE(fmt_) AI_BUFFER_FMT_UNPACK(fmt_, 0xF, 17)
+
+#define AI_BUFFER_FMT_GET_BITS(fmt_) AI_BUFFER_FMT_UNPACK(fmt_, 0x7F, 7)
+
+#define AI_BUFFER_FMT_SET_BITS(bits_) AI_BUFFER_FMT_PACK((bits_), 0x7F, 7)
+
+#define AI_BUFFER_FMT_GET_FBITS(fmt_) ((ai_i8)AI_BUFFER_FMT_UNPACK(fmt_, 0x7F, 0) - 64)
+
+#define AI_BUFFER_FMT_SET_FBITS(fbits_) AI_BUFFER_FMT_PACK((fbits_) + 64, 0x7F, 0)
+
+#define AI_BUFFER_FMT_SET(type_id_, sign_bit_, float_bit_, bits_, fbits_) \
+ AI_BUFFER_FMT_OBJ(AI_BUFFER_FMT_PACK(float_bit_, 0x1, 24) | \
+ AI_BUFFER_FMT_PACK(sign_bit_, 0x1, 23) | AI_BUFFER_FMT_PACK(0, 0x3, 21) | \
+ AI_BUFFER_FMT_PACK(type_id_, 0xF, 17) | AI_BUFFER_FMT_PACK(0, 0x7, 14) | \
+ AI_BUFFER_FMT_SET_BITS(bits_) | AI_BUFFER_FMT_SET_FBITS(fbits_))
+
+#define AI_BUFFER_FMT_GET(fmt_) (AI_BUFFER_FMT_OBJ(fmt_) & 0x01FFFFFF)
+
+#define AI_BUFFER_FORMAT(buf_) AI_BUFFER_FMT_GET((buf_)->format)
+#define AI_BUFFER_WIDTH(buf_) ((buf_)->width)
+#define AI_BUFFER_HEIGHT(buf_) ((buf_)->height)
+#define AI_BUFFER_CHANNELS(buf_) ((buf_)->channels)
+#define AI_BUFFER_N_BATCHES(buf_) ((buf_)->n_batches)
+#define AI_BUFFER_DATA(buf_, type_) ((type_*)((buf_)->data))
+
+#define AI_BUFFER_META_INFO(buf_) ((buf_)->meta_info)
+
+#define AI_BUFFER_META_INFO_INTQ(meta_) \
+ ((meta_) && ((meta_)->flags & AI_BUFFER_META_HAS_INTQ_INFO)) ? ((meta_)->intq_info) \
+ : NULL // NOLINT
+
+#define AI_BUFFER_META_INFO_INTQ_GET_SCALE(meta_, pos_) \
+ ((AI_BUFFER_META_INFO_INTQ(meta_)) \
+ ? AI_INTQ_INFO_LIST_SCALE(AI_BUFFER_META_INFO_INTQ(meta_), ai_float, pos_) \
+ : 0)
+
+#define AI_BUFFER_META_INFO_INTQ_GET_ZEROPOINT(meta_, pos_) \
+ ((AI_BUFFER_META_INFO_INTQ(meta_)) \
+ ? ((AI_INTQ_INFO_LIST_FLAGS(AI_BUFFER_META_INFO_INTQ(meta_)) & \
+ AI_BUFFER_META_FLAG_ZEROPOINT_U8) \
+ ? AI_INTQ_INFO_LIST_ZEROPOINT(AI_BUFFER_META_INFO_INTQ(meta_), ai_u8, pos_) \
+ : AI_INTQ_INFO_LIST_ZEROPOINT(AI_BUFFER_META_INFO_INTQ(meta_), ai_i8, pos_)) \
+ : 0)
+
+#define AI_BUFFER_META_INFO_INIT(flags_, intq_info_) \
+ { .flags = (flags_), .intq_info = AI_PACK(intq_info_) }
+
+#define AI_BUFFER_SIZE(buf_) (((buf_)->width) * ((buf_)->height) * ((buf_)->channels))
+
+#define AI_BUFFER_BYTE_SIZE(count_, fmt_) ((((count_)*AI_BUFFER_FMT_GET_BITS(fmt_)) + 4) >> 3)
+
+/*!
+ * @enum buffer formats enum list
+ * @ingroup ai_platform
+ *
+ * List of supported ai_buffer format types.
+ */
+enum {
+ AI_BUFFER_FORMAT_NONE = AI_BUFFER_FMT_SET(AI_BUFFER_FMT_TYPE_NONE, 0, 0, 0, 0),
+ AI_BUFFER_FORMAT_FLOAT = AI_BUFFER_FMT_SET(AI_BUFFER_FMT_TYPE_FLOAT, 1, 1, 32, 0),
+
+ AI_BUFFER_FORMAT_U8 = AI_BUFFER_FMT_SET(AI_BUFFER_FMT_TYPE_Q, 0, 0, 8, 0),
+ AI_BUFFER_FORMAT_U16 = AI_BUFFER_FMT_SET(AI_BUFFER_FMT_TYPE_Q, 0, 0, 16, 0),
+ AI_BUFFER_FORMAT_S8 = AI_BUFFER_FMT_SET(AI_BUFFER_FMT_TYPE_Q, 1, 0, 8, 0),
+ AI_BUFFER_FORMAT_S16 = AI_BUFFER_FMT_SET(AI_BUFFER_FMT_TYPE_Q, 1, 0, 16, 0),
+
+ AI_BUFFER_FORMAT_Q = AI_BUFFER_FMT_SET(AI_BUFFER_FMT_TYPE_Q, 1, 0, 0, 0),
+ AI_BUFFER_FORMAT_Q7 = AI_BUFFER_FMT_SET(AI_BUFFER_FMT_TYPE_Q, 1, 0, 8, 7),
+ AI_BUFFER_FORMAT_Q15 = AI_BUFFER_FMT_SET(AI_BUFFER_FMT_TYPE_Q, 1, 0, 16, 15),
+
+ AI_BUFFER_FORMAT_UQ = AI_BUFFER_FMT_SET(AI_BUFFER_FMT_TYPE_Q, 0, 0, 0, 0),
+ AI_BUFFER_FORMAT_UQ7 = AI_BUFFER_FMT_SET(AI_BUFFER_FMT_TYPE_Q, 0, 0, 8, 7),
+ AI_BUFFER_FORMAT_UQ15 = AI_BUFFER_FMT_SET(AI_BUFFER_FMT_TYPE_Q, 0, 0, 16, 15),
+
+ AI_BUFFER_FORMAT_BOOL = AI_BUFFER_FMT_SET(AI_BUFFER_FMT_TYPE_BOOL, 0, 0, 8, 0),
+};
+
+/******************************************************************************/
+
+/* printf formats */
+#define SSIZET_FMT "%" PRIu32
Review comment:
nit: can't see where these are used
##########
File path: src/runtime/crt/contrib/stm32/ai_platform.h
##########
@@ -0,0 +1,383 @@
+/*
+ * 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.
+ */
+
+/*!
+ * \file ai_platform.h
+ * \brief Definitions of AI platform public APIs types
+ */
+
+// LINT_C_FILE
+
+#ifndef AI_PLATFORM_H
+#define AI_PLATFORM_H
+#pragma once
+
+#include <inttypes.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#ifndef AI_PLATFORM_API_MAJOR
+#define AI_PLATFORM_API_MAJOR (0)
+#endif
+#ifndef AI_PLATFORM_API_MINOR
+#define AI_PLATFORM_API_MINOR (6)
+#endif
+#ifndef AI_PLATFORM_API_MICRO
+#define AI_PLATFORM_API_MICRO (0)
+#endif
+
+#define AI_PLATFORM_API_VERSION \
+ AI_VERSION(AI_PLATFORM_API_MAJOR, AI_PLATFORM_API_MINOR, AI_PLATFORM_API_MICRO)
+
+#ifndef AI_TOOLS_API_VERSION_MAJOR
+#define AI_TOOLS_API_VERSION_MAJOR (1)
+#endif
+#ifndef AI_TOOLS_API_VERSION_MINOR
+#define AI_TOOLS_API_VERSION_MINOR (4)
+#endif
+#ifndef AI_TOOLS_API_VERSION_MICRO
+#define AI_TOOLS_API_VERSION_MICRO (0)
+#endif
+
+#define AI_TOOLS_API_VERSION \
+ AI_VERSION(AI_TOOLS_API_VERSION_MAJOR, AI_TOOLS_API_VERSION_MINOR, AI_TOOLS_API_VERSION_MICRO)
+
+#define AI_TOOLS_API_VERSION_1_3 AI_VERSION(1, 3, 0)
+
+/******************************************************************************/
+#ifdef __cplusplus
+#define AI_API_DECLARE_BEGIN extern "C" {
+#define AI_API_DECLARE_END }
+#else
+#include <stdbool.h>
+#define AI_API_DECLARE_BEGIN /* AI_API_DECLARE_BEGIN */
+#define AI_API_DECLARE_END /* AI_API_DECLARE_END */
+#endif
+
+/******************************************************************************/
+#if defined(_MSC_VER)
+#define AI_API_ENTRY __declspec(dllexport)
+#define AI_ALIGNED(x) /* AI_ALIGNED(x) */
+#elif defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
+#define AI_API_ENTRY /* AI_API_ENTRY */
+#define AI_ALIGNED(x) AI_CONCAT(AI_ALIGNED_, x)
+#define AI_ALIGNED_1 _Pragma("data_alignment = 1")
+#define AI_ALIGNED_2 _Pragma("data_alignment = 2")
+#define AI_ALIGNED_4 _Pragma("data_alignment = 4")
+#define AI_ALIGNED_8 _Pragma("data_alignment = 8")
+#define AI_ALIGNED_16 _Pragma("data_alignment = 16")
+#define AI_ALIGNED_32 _Pragma("data_alignment = 32")
+#elif defined(__CC_ARM)
+#define AI_API_ENTRY __attribute__((visibility("default")))
+#define AI_ALIGNED(x) __attribute__((aligned(x)))
+/* Keil disallows anonymous union initialization by default */
+#pragma anon_unions
+#elif defined(__GNUC__)
+#define AI_API_ENTRY __attribute__((visibility("default")))
+#define AI_ALIGNED(x) __attribute__((aligned(x)))
+#else
+/* Dynamic libraries are not supported by the compiler */
+#define AI_API_ENTRY /* AI_API_ENTRY */
+#define AI_ALIGNED(x) /* AI_ALIGNED(x) */
+#endif
+
+#define AI_HANDLE_PTR(ptr_) ((ai_handle)(ptr_))
+#define AI_HANDLE_NULL AI_HANDLE_PTR(NULL)
+
+#define AI_HANDLE_FUNC_PTR(func) ((ai_handle_func)(func))
+
+#define AI_NETWORK_PARAMS_INIT(params_, activations_) \
+ { .params = params_, .activations = activations_ }
+
+/*! ai_intq_info struct handlers **********************************************/
+#define INTQ_CONST const
+// #define INTQ_CONST
+
+#define AI_INTQ_INFO_LIST(list_) ((list_)->info)
+
+#define AI_INTQ_INFO_LIST_FLAGS(list_) ((list_) ? (list_)->flags : 0)
+
+#define AI_INTQ_INFO_LIST_SIZE(list_) ((list_) ? (list_)->size : 0)
+
+#define AI_HAS_INTQ_INFO_LIST(list_) ((list_) ? (((list_)->info) && ((list_)->size > 0)) : false)
+
+#define AI_INTQ_INFO_LIST_SCALE(list_, type_, pos_) \
+ (((list_) && (list_)->info && ((pos_) < (list_)->size)) \
+ ? ((type_*)((list_)->info->scale))[(pos_)] \
+ : 0)
+
+#define AI_INTQ_INFO_LIST_ZEROPOINT(list_, type_, pos_) \
+ (((list_) && (list_)->info && ((pos_) < (list_)->size)) \
+ ? ((type_*)((list_)->info->zeropoint))[(pos_)] \
+ : 0)
+
+/*! ai_buffer format handlers *************************************************/
+
+/*!
+ * @enum buffer format definition
+ * @ingroup ai_platform
+ *
+ * 32 bit signed format list.
+ */
+typedef int32_t ai_buffer_format;
+
+/*! ai_buffer_meta flags ******************************************************/
+#define AI_BUFFER_META_HAS_INTQ_INFO (0x1U << 0)
+#define AI_BUFFER_META_FLAG_SCALE_FLOAT (0x1U << 0)
+#define AI_BUFFER_META_FLAG_ZEROPOINT_U8 (0x1U << 1)
+#define AI_BUFFER_META_FLAG_ZEROPOINT_S8 (0x1U << 2)
+
+/*! ai_buffer format variable flags *******************************************/
+#define AI_BUFFER_FMT_TYPE_NONE (0x0)
+#define AI_BUFFER_FMT_TYPE_FLOAT (0x1)
+#define AI_BUFFER_FMT_TYPE_Q (0x2)
+#define AI_BUFFER_FMT_TYPE_BOOL (0x3)
+
+#define AI_BUFFER_FMT_FLAG_CONST (0x1U << 30)
+#define AI_BUFFER_FMT_FLAG_STATIC (0x1U << 29)
+#define AI_BUFFER_FMT_FLAG_IS_IO (0x1U << 27)
+
+#define AI_BUFFER_FMT_PACK(value_, mask_, bits_) (((value_) & (mask_)) << (bits_))
+
+#define AI_BUFFER_FMT_UNPACK(fmt_, mask_, bits_) ((AI_BUFFER_FMT_OBJ(fmt_) >> (bits_)) & (mask_))
+
+#define AI_BUFFER_FMT_OBJ(fmt_) ((ai_buffer_format)(fmt_))
+
+#define AI_BUFFER_FMT_GET_FLOAT(fmt_) AI_BUFFER_FMT_UNPACK(fmt_, 0x1, 24)
+
+#define AI_BUFFER_FMT_GET_SIGN(fmt_) AI_BUFFER_FMT_UNPACK(fmt_, 0x1, 23)
+
+#define AI_BUFFER_FMT_GET_TYPE(fmt_) AI_BUFFER_FMT_UNPACK(fmt_, 0xF, 17)
+
+#define AI_BUFFER_FMT_GET_BITS(fmt_) AI_BUFFER_FMT_UNPACK(fmt_, 0x7F, 7)
+
+#define AI_BUFFER_FMT_SET_BITS(bits_) AI_BUFFER_FMT_PACK((bits_), 0x7F, 7)
+
+#define AI_BUFFER_FMT_GET_FBITS(fmt_) ((ai_i8)AI_BUFFER_FMT_UNPACK(fmt_, 0x7F, 0) - 64)
+
+#define AI_BUFFER_FMT_SET_FBITS(fbits_) AI_BUFFER_FMT_PACK((fbits_) + 64, 0x7F, 0)
+
+#define AI_BUFFER_FMT_SET(type_id_, sign_bit_, float_bit_, bits_, fbits_) \
+ AI_BUFFER_FMT_OBJ(AI_BUFFER_FMT_PACK(float_bit_, 0x1, 24) | \
+ AI_BUFFER_FMT_PACK(sign_bit_, 0x1, 23) | AI_BUFFER_FMT_PACK(0, 0x3, 21) | \
+ AI_BUFFER_FMT_PACK(type_id_, 0xF, 17) | AI_BUFFER_FMT_PACK(0, 0x7, 14) | \
+ AI_BUFFER_FMT_SET_BITS(bits_) | AI_BUFFER_FMT_SET_FBITS(fbits_))
+
+#define AI_BUFFER_FMT_GET(fmt_) (AI_BUFFER_FMT_OBJ(fmt_) & 0x01FFFFFF)
+
+#define AI_BUFFER_FORMAT(buf_) AI_BUFFER_FMT_GET((buf_)->format)
+#define AI_BUFFER_WIDTH(buf_) ((buf_)->width)
+#define AI_BUFFER_HEIGHT(buf_) ((buf_)->height)
+#define AI_BUFFER_CHANNELS(buf_) ((buf_)->channels)
+#define AI_BUFFER_N_BATCHES(buf_) ((buf_)->n_batches)
+#define AI_BUFFER_DATA(buf_, type_) ((type_*)((buf_)->data))
+
+#define AI_BUFFER_META_INFO(buf_) ((buf_)->meta_info)
+
+#define AI_BUFFER_META_INFO_INTQ(meta_) \
+ ((meta_) && ((meta_)->flags & AI_BUFFER_META_HAS_INTQ_INFO)) ? ((meta_)->intq_info) \
+ : NULL // NOLINT
+
+#define AI_BUFFER_META_INFO_INTQ_GET_SCALE(meta_, pos_) \
+ ((AI_BUFFER_META_INFO_INTQ(meta_)) \
+ ? AI_INTQ_INFO_LIST_SCALE(AI_BUFFER_META_INFO_INTQ(meta_), ai_float, pos_) \
+ : 0)
+
+#define AI_BUFFER_META_INFO_INTQ_GET_ZEROPOINT(meta_, pos_) \
+ ((AI_BUFFER_META_INFO_INTQ(meta_)) \
+ ? ((AI_INTQ_INFO_LIST_FLAGS(AI_BUFFER_META_INFO_INTQ(meta_)) & \
+ AI_BUFFER_META_FLAG_ZEROPOINT_U8) \
+ ? AI_INTQ_INFO_LIST_ZEROPOINT(AI_BUFFER_META_INFO_INTQ(meta_), ai_u8, pos_) \
+ : AI_INTQ_INFO_LIST_ZEROPOINT(AI_BUFFER_META_INFO_INTQ(meta_), ai_i8, pos_)) \
+ : 0)
+
+#define AI_BUFFER_META_INFO_INIT(flags_, intq_info_) \
+ { .flags = (flags_), .intq_info = AI_PACK(intq_info_) }
+
+#define AI_BUFFER_SIZE(buf_) (((buf_)->width) * ((buf_)->height) * ((buf_)->channels))
+
+#define AI_BUFFER_BYTE_SIZE(count_, fmt_) ((((count_)*AI_BUFFER_FMT_GET_BITS(fmt_)) + 4) >> 3)
+
+/*!
+ * @enum buffer formats enum list
+ * @ingroup ai_platform
+ *
+ * List of supported ai_buffer format types.
+ */
+enum {
+ AI_BUFFER_FORMAT_NONE = AI_BUFFER_FMT_SET(AI_BUFFER_FMT_TYPE_NONE, 0, 0, 0, 0),
+ AI_BUFFER_FORMAT_FLOAT = AI_BUFFER_FMT_SET(AI_BUFFER_FMT_TYPE_FLOAT, 1, 1, 32, 0),
+
+ AI_BUFFER_FORMAT_U8 = AI_BUFFER_FMT_SET(AI_BUFFER_FMT_TYPE_Q, 0, 0, 8, 0),
+ AI_BUFFER_FORMAT_U16 = AI_BUFFER_FMT_SET(AI_BUFFER_FMT_TYPE_Q, 0, 0, 16, 0),
+ AI_BUFFER_FORMAT_S8 = AI_BUFFER_FMT_SET(AI_BUFFER_FMT_TYPE_Q, 1, 0, 8, 0),
+ AI_BUFFER_FORMAT_S16 = AI_BUFFER_FMT_SET(AI_BUFFER_FMT_TYPE_Q, 1, 0, 16, 0),
+
+ AI_BUFFER_FORMAT_Q = AI_BUFFER_FMT_SET(AI_BUFFER_FMT_TYPE_Q, 1, 0, 0, 0),
+ AI_BUFFER_FORMAT_Q7 = AI_BUFFER_FMT_SET(AI_BUFFER_FMT_TYPE_Q, 1, 0, 8, 7),
+ AI_BUFFER_FORMAT_Q15 = AI_BUFFER_FMT_SET(AI_BUFFER_FMT_TYPE_Q, 1, 0, 16, 15),
+
+ AI_BUFFER_FORMAT_UQ = AI_BUFFER_FMT_SET(AI_BUFFER_FMT_TYPE_Q, 0, 0, 0, 0),
+ AI_BUFFER_FORMAT_UQ7 = AI_BUFFER_FMT_SET(AI_BUFFER_FMT_TYPE_Q, 0, 0, 8, 7),
+ AI_BUFFER_FORMAT_UQ15 = AI_BUFFER_FMT_SET(AI_BUFFER_FMT_TYPE_Q, 0, 0, 16, 15),
+
+ AI_BUFFER_FORMAT_BOOL = AI_BUFFER_FMT_SET(AI_BUFFER_FMT_TYPE_BOOL, 0, 0, 8, 0),
+};
+
+/******************************************************************************/
+
+/* printf formats */
+#define SSIZET_FMT "%" PRIu32
+#define AII32_FMT "%" PRId32
+#define AIU32_FMT "%" PRIu32
+
+typedef uint8_t ai_custom_type_signature;
+
+typedef void* ai_handle;
+
+typedef void (*ai_handle_func)(void*);
+
+typedef float ai_float;
+typedef double ai_double;
Review comment:
nit: of these i just see ai_float, ai_u8, u16, u32 used
##########
File path: src/runtime/crt/contrib/stm32/ai_runtime_api.h
##########
@@ -0,0 +1,226 @@
+/*
+ * 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.
+ */
+
+/*!
+ * \file ai_runtime_api.h
+ * \brief The runtime API for the TVM generated C code.
+ */
+
+#ifndef TVM_RUNTIME_CRT_CONTRIB_STM32_AI_RUNTIME_API_H_
+#define TVM_RUNTIME_CRT_CONTRIB_STM32_AI_RUNTIME_API_H_
+
+#include "ai_platform.h"
+#include "dlpack/dlpack.h" // From TVM
+#include "tvm/runtime/c_runtime_api.h" // From TVM
+
+//
+// This describes current ai_runtime version
+//
+#define AI_PLATFORM_RUNTIME_MAJOR 1
+#define AI_PLATFORM_RUNTIME_MINOR 0
+#define AI_PLATFORM_RUNTIME_MICRO 0
+
+#define AI_STATIC static
+
+#if defined(_MSC_VER)
+#define AI_INLINE __inline
+#elif defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
+#define AI_INLINE inline
+#elif defined(__CC_ARM)
+#define AI_INLINE __inline
+/* Keil disallows anonymous union initialization by default */
+#pragma anon_unions
+#elif defined(__GNUC__)
+#define AI_INLINE __inline
+#else
+/* Dynamic libraries are not supported by the compiler */
+#endif
+
+/*********************************************************/
+
+typedef uint8_t* ai_ptr;
+
+typedef enum { AI_STATUS_OK = 0, AI_STATUS_ERROR = 1, AI_STATUS_DELEGATE_ERROR = 2 } ai_status;
+
+// =======================================================
+// ai_quantization_info
+//
+// Parameters for asymmetric quantization across a dimension (i.e
+// per output channel quantization).
+// quantized_dimension specifies which dimension the scales and
+// zero_points correspond to.
+// For a particular value in quantized_dimension, quantized values
+// can be converted back to float using:
+// real_value = scale * (quantized_value - zero_point)
+// =======================================================
+
+typedef struct {
+ /*!
+ * \brief The quantization info, if quantized
+ */
+ float* scale;
+ int32_t* zero_point;
+ int32_t dim;
+} ai_quantization_info;
+
+// =======================================================
+// ai_tensor
+// =======================================================
+
+typedef struct {
+ /*!
+ * \brief The TVM tensor.
+ */
+ DLTensor dltensor;
+ /*!
+ * \brief The quantization info, if quantized
+ */
+ ai_quantization_info* quant;
+} ai_tensor;
+
+// =======================================================
+// get_dltensor
+// =======================================================
+AI_STATIC AI_INLINE DLTensor* get_dltensor(ai_tensor* tensor) { return &tensor->dltensor; }
Review comment:
i don't see this function exercised--consider deleting it
##########
File path: python/tvm/contrib/stm32/BaseEmitter.py
##########
@@ -0,0 +1,1257 @@
+# 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.
+
+# pylint: disable=line-too-long
+
+"""Code emission for the STM32 targets."""
+
+import json
+import os
+import re
+import tarfile
+
+from datetime import datetime
+
+import numpy as np
+
+import tvm
+from tvm.contrib import utils
+
+AI_TOOLS_VERSION_MAJOR = 1
+AI_TOOLS_VERSION_MINOR = 8
+AI_TOOLS_VERSION_MICRO = 0
+
+AI_API_VERSION_MAJOR = 1
+AI_API_VERSION_MINOR = 0
+AI_API_VERSION_MICRO = 0
+
+AI_TOOLS_REVISION = "v1"
+
+DBAR = "=" * 60
+
+
+def _fix_name(node_name):
+ """Replace ':' with '_' in names like 'InputImg:0'"""
+ return node_name.replace(":", "_")
+
+
+def get_input_tensor_name(node_name):
+ return _fix_name(node_name)
+
+
+def get_output_tensor_name(node_name, idx):
+ return _fix_name(node_name) + "_" + str(idx)
+
+
+def get_tensor_data_name(tensor_name):
+ return tensor_name + ".dltensor.data"
+
+
+def get_node_args_name(node_name):
+ return _fix_name(node_name) + "_args"
+
+
+def get_node_arg_types_name(node_name):
+ return _fix_name(node_name) + "_arg_type_ids"
+
+
+def _get_type_size(dltype):
+
+ if dltype in ("uint64", "int64"):
+ return 8
+ if dltype in ("uint32", "int32", "float32"):
+ return 4
+ if dltype in ("uint16", "int16"):
+ return 2
+ if dltype in ("uint8", "int8"):
+ return 1
+
+ raise ValueError(f"Data type {dltype} is not supported")
+
+
+def _get_type_data(dltype):
+
+ if dltype == "uint64":
+ return "kDLUInt, 64, 1"
+ if dltype == "int64":
+ return "kDLInt, 64, 1"
+ if dltype == "float32":
+ return "kDLFloat, 32, 1"
+ if dltype == "uint32":
+ return "kDLUInt, 32, 1"
+ if dltype == "int32":
+ return "kDLInt, 32, 1"
+ if dltype == "uint16":
+ return "kDLUInt, 16, 1"
+ if dltype == "int16":
+ return "kDLInt, 16, 1"
+ if dltype == "uint8":
+ return "kDLUInt, 8, 1"
+ if dltype == "int8":
+ return "kDLInt, 8, 1"
+
+ raise ValueError(f"Data type {dltype} is not supported")
+
+
+def get_aligned_offset(offset, dltype):
+
+ align = _get_type_size(dltype)
+
+ if offset % align != 0:
+ offset = offset + (align - offset % align)
+
+ return offset
+
+
+def _get_tensor_elts(dims):
+ size = 1
+ for dim in dims:
+ size = size * dim
+ return size
+
+
+def get_tensor_size(dims, dltype):
+ size = _get_tensor_elts(dims)
+ return size * _get_type_size(dltype)
+
+
+def _emit_tensor_shape(dl_tensor_name, ndim, shape, strides, out_c):
+ out_c.write(f"AI_STATIC int64_t {dl_tensor_name}_shape[{ndim}] = {{{shape[1:-1]}}}; \n")
+ assert strides is None, f"###Error: non-compact tensors are not handled yet."
+ out_c.write(f"AI_STATIC int64_t {dl_tensor_name}_strides[{ndim}] = {{}}; \n")
+
+
+def _emit_tensor_quant(dl_tensor_name, quantization_map, out_c):
+
+ if dl_tensor_name in quantization_map:
+ quantization = quantization_map[dl_tensor_name]
+ else:
+ quantization = None
+
+ if quantization is not None:
+ # minval = quantization['min']
+ # maxval = quantization['max']
+ scale = quantization["scale"]
+ zero_point = quantization["zero_point"]
+ # dim = quantization['dim']
+
+ #
+ # Sometimes we get a scalar with ScaleAsNumpy.
+ # This seem to mean not quantized ?
+ #
+ if not isinstance(scale, np.ndarray):
+ assert scale == 0.0, f"Non-quantized tensor with scale != 0.0"
+ assert (
+ not isinstance(zero_point, np.ndarray) and zero_point == 0
+ ), f"Non-quantized tensor with zero_point != 0"
+ return None
+
+ scale_size = len(scale)
+ zero_point_size = len(zero_point)
+
+ assert len(scale) == len(
+ zero_point
+ ), f"Inconsistent quantizations scale:{scale} vs zero-point:{zero_point}"
+
+ if len(scale) == 1:
+ quant_name = dl_tensor_name + "_quant"
+ out_c.write(f"AI_STATIC float {quant_name}_scale[{scale_size}] = {{ ")
+ for val in scale:
+ out_c.write(f"{val}, ")
+ out_c.write(f"}};\n")
+ out_c.write(f"AI_STATIC int32_t {quant_name}_zero_point[{zero_point_size}] = {{ ")
+ for val in zero_point:
+ out_c.write(f"{val}, ")
+ out_c.write(f"}};\n")
+ out_c.write(f"AI_STATIC ai_quantization_info {quant_name} = {{\n")
+ out_c.write(f" .scale = {quant_name}_scale,\n")
+ out_c.write(f" .zero_point = {quant_name}_zero_point,\n")
+ out_c.write(f" .dim = -1\n")
+ out_c.write(f"}}; \n")
+
+ return quant_name
+
+ return None
+
+
+def emit_tensor_init(dl_tensor_name, tensor, quantization_map, out_c):
+ """Emit tensor definition."""
+ dltype = tensor["dltype"]
+ dims = tensor["dims"]
+ strides = tensor["strides"]
+ if "device" in tensor:
+ device = tensor["device"]
+ else:
+ device = "kDLCPU"
+ # storage_id = tensor['storage_id']
+ byte_offset = tensor["byte_offset"]
+ # size = tensor['size']
+ dtype = _get_type_data(dltype)
+ ndim = len(dims)
+ shape = str(dims)
+ _emit_tensor_shape(dl_tensor_name, ndim, shape, strides, out_c)
+
+ #
+ # Quantization
+ #
+ if quantization_map is not None:
+ quant_name = _emit_tensor_quant(dl_tensor_name, quantization_map, out_c)
+ else:
+ quant_name = None
+
+ #
+ # Contents
+ #
+ out_c.write(f"AI_ALIGNED({8}) AI_STATIC ai_tensor {dl_tensor_name} = {{ \n")
Review comment:
a suggestion: there are a lot of "templates" like these that might be easier to understand if you write them as python heredoc and take more advantage of the format() function:
```
AI_TENSOR_TEMPLATE = """\
AI_ALIGNED(8) AI_STATIC ai_tensor {dl_tensor_name} = {{
.dltensor = {{
.data = (ai_ptr)(NULL),
.device = {{ {tensor.get("device", "kDLCPU")} }},
.ndim = {len(tensor["dims"])},
# etc
```
and then
```
out_c.write(AI_TENSOR_TEMPLATE.format(device_name=device_name, tensor=tensor))
```
##########
File path: src/runtime/crt/contrib/stm32/ai_platform.h
##########
@@ -0,0 +1,383 @@
+/*
+ * 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.
+ */
+
+/*!
+ * \file ai_platform.h
+ * \brief Definitions of AI platform public APIs types
+ */
+
+// LINT_C_FILE
+
+#ifndef AI_PLATFORM_H
+#define AI_PLATFORM_H
+#pragma once
+
+#include <inttypes.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#ifndef AI_PLATFORM_API_MAJOR
+#define AI_PLATFORM_API_MAJOR (0)
+#endif
+#ifndef AI_PLATFORM_API_MINOR
+#define AI_PLATFORM_API_MINOR (6)
+#endif
+#ifndef AI_PLATFORM_API_MICRO
+#define AI_PLATFORM_API_MICRO (0)
+#endif
+
+#define AI_PLATFORM_API_VERSION \
+ AI_VERSION(AI_PLATFORM_API_MAJOR, AI_PLATFORM_API_MINOR, AI_PLATFORM_API_MICRO)
+
+#ifndef AI_TOOLS_API_VERSION_MAJOR
+#define AI_TOOLS_API_VERSION_MAJOR (1)
+#endif
+#ifndef AI_TOOLS_API_VERSION_MINOR
+#define AI_TOOLS_API_VERSION_MINOR (4)
+#endif
+#ifndef AI_TOOLS_API_VERSION_MICRO
+#define AI_TOOLS_API_VERSION_MICRO (0)
+#endif
+
+#define AI_TOOLS_API_VERSION \
+ AI_VERSION(AI_TOOLS_API_VERSION_MAJOR, AI_TOOLS_API_VERSION_MINOR, AI_TOOLS_API_VERSION_MICRO)
+
+#define AI_TOOLS_API_VERSION_1_3 AI_VERSION(1, 3, 0)
+
+/******************************************************************************/
+#ifdef __cplusplus
+#define AI_API_DECLARE_BEGIN extern "C" {
+#define AI_API_DECLARE_END }
+#else
+#include <stdbool.h>
+#define AI_API_DECLARE_BEGIN /* AI_API_DECLARE_BEGIN */
+#define AI_API_DECLARE_END /* AI_API_DECLARE_END */
+#endif
+
+/******************************************************************************/
+#if defined(_MSC_VER)
+#define AI_API_ENTRY __declspec(dllexport)
+#define AI_ALIGNED(x) /* AI_ALIGNED(x) */
+#elif defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
+#define AI_API_ENTRY /* AI_API_ENTRY */
+#define AI_ALIGNED(x) AI_CONCAT(AI_ALIGNED_, x)
+#define AI_ALIGNED_1 _Pragma("data_alignment = 1")
+#define AI_ALIGNED_2 _Pragma("data_alignment = 2")
+#define AI_ALIGNED_4 _Pragma("data_alignment = 4")
+#define AI_ALIGNED_8 _Pragma("data_alignment = 8")
+#define AI_ALIGNED_16 _Pragma("data_alignment = 16")
+#define AI_ALIGNED_32 _Pragma("data_alignment = 32")
+#elif defined(__CC_ARM)
+#define AI_API_ENTRY __attribute__((visibility("default")))
+#define AI_ALIGNED(x) __attribute__((aligned(x)))
+/* Keil disallows anonymous union initialization by default */
+#pragma anon_unions
+#elif defined(__GNUC__)
+#define AI_API_ENTRY __attribute__((visibility("default")))
+#define AI_ALIGNED(x) __attribute__((aligned(x)))
+#else
+/* Dynamic libraries are not supported by the compiler */
+#define AI_API_ENTRY /* AI_API_ENTRY */
+#define AI_ALIGNED(x) /* AI_ALIGNED(x) */
+#endif
+
+#define AI_HANDLE_PTR(ptr_) ((ai_handle)(ptr_))
+#define AI_HANDLE_NULL AI_HANDLE_PTR(NULL)
+
+#define AI_HANDLE_FUNC_PTR(func) ((ai_handle_func)(func))
+
+#define AI_NETWORK_PARAMS_INIT(params_, activations_) \
+ { .params = params_, .activations = activations_ }
+
+/*! ai_intq_info struct handlers **********************************************/
+#define INTQ_CONST const
+// #define INTQ_CONST
+
+#define AI_INTQ_INFO_LIST(list_) ((list_)->info)
+
+#define AI_INTQ_INFO_LIST_FLAGS(list_) ((list_) ? (list_)->flags : 0)
+
+#define AI_INTQ_INFO_LIST_SIZE(list_) ((list_) ? (list_)->size : 0)
+
+#define AI_HAS_INTQ_INFO_LIST(list_) ((list_) ? (((list_)->info) && ((list_)->size > 0)) : false)
+
+#define AI_INTQ_INFO_LIST_SCALE(list_, type_, pos_) \
+ (((list_) && (list_)->info && ((pos_) < (list_)->size)) \
+ ? ((type_*)((list_)->info->scale))[(pos_)] \
+ : 0)
+
+#define AI_INTQ_INFO_LIST_ZEROPOINT(list_, type_, pos_) \
+ (((list_) && (list_)->info && ((pos_) < (list_)->size)) \
+ ? ((type_*)((list_)->info->zeropoint))[(pos_)] \
+ : 0)
+
+/*! ai_buffer format handlers *************************************************/
+
+/*!
+ * @enum buffer format definition
+ * @ingroup ai_platform
+ *
+ * 32 bit signed format list.
+ */
+typedef int32_t ai_buffer_format;
+
+/*! ai_buffer_meta flags ******************************************************/
+#define AI_BUFFER_META_HAS_INTQ_INFO (0x1U << 0)
+#define AI_BUFFER_META_FLAG_SCALE_FLOAT (0x1U << 0)
+#define AI_BUFFER_META_FLAG_ZEROPOINT_U8 (0x1U << 1)
+#define AI_BUFFER_META_FLAG_ZEROPOINT_S8 (0x1U << 2)
+
+/*! ai_buffer format variable flags *******************************************/
+#define AI_BUFFER_FMT_TYPE_NONE (0x0)
+#define AI_BUFFER_FMT_TYPE_FLOAT (0x1)
+#define AI_BUFFER_FMT_TYPE_Q (0x2)
+#define AI_BUFFER_FMT_TYPE_BOOL (0x3)
+
+#define AI_BUFFER_FMT_FLAG_CONST (0x1U << 30)
+#define AI_BUFFER_FMT_FLAG_STATIC (0x1U << 29)
+#define AI_BUFFER_FMT_FLAG_IS_IO (0x1U << 27)
+
+#define AI_BUFFER_FMT_PACK(value_, mask_, bits_) (((value_) & (mask_)) << (bits_))
+
+#define AI_BUFFER_FMT_UNPACK(fmt_, mask_, bits_) ((AI_BUFFER_FMT_OBJ(fmt_) >> (bits_)) & (mask_))
+
+#define AI_BUFFER_FMT_OBJ(fmt_) ((ai_buffer_format)(fmt_))
+
+#define AI_BUFFER_FMT_GET_FLOAT(fmt_) AI_BUFFER_FMT_UNPACK(fmt_, 0x1, 24)
+
+#define AI_BUFFER_FMT_GET_SIGN(fmt_) AI_BUFFER_FMT_UNPACK(fmt_, 0x1, 23)
+
+#define AI_BUFFER_FMT_GET_TYPE(fmt_) AI_BUFFER_FMT_UNPACK(fmt_, 0xF, 17)
+
+#define AI_BUFFER_FMT_GET_BITS(fmt_) AI_BUFFER_FMT_UNPACK(fmt_, 0x7F, 7)
+
+#define AI_BUFFER_FMT_SET_BITS(bits_) AI_BUFFER_FMT_PACK((bits_), 0x7F, 7)
+
+#define AI_BUFFER_FMT_GET_FBITS(fmt_) ((ai_i8)AI_BUFFER_FMT_UNPACK(fmt_, 0x7F, 0) - 64)
+
+#define AI_BUFFER_FMT_SET_FBITS(fbits_) AI_BUFFER_FMT_PACK((fbits_) + 64, 0x7F, 0)
+
+#define AI_BUFFER_FMT_SET(type_id_, sign_bit_, float_bit_, bits_, fbits_) \
+ AI_BUFFER_FMT_OBJ(AI_BUFFER_FMT_PACK(float_bit_, 0x1, 24) | \
+ AI_BUFFER_FMT_PACK(sign_bit_, 0x1, 23) | AI_BUFFER_FMT_PACK(0, 0x3, 21) | \
+ AI_BUFFER_FMT_PACK(type_id_, 0xF, 17) | AI_BUFFER_FMT_PACK(0, 0x7, 14) | \
+ AI_BUFFER_FMT_SET_BITS(bits_) | AI_BUFFER_FMT_SET_FBITS(fbits_))
+
+#define AI_BUFFER_FMT_GET(fmt_) (AI_BUFFER_FMT_OBJ(fmt_) & 0x01FFFFFF)
+
+#define AI_BUFFER_FORMAT(buf_) AI_BUFFER_FMT_GET((buf_)->format)
+#define AI_BUFFER_WIDTH(buf_) ((buf_)->width)
+#define AI_BUFFER_HEIGHT(buf_) ((buf_)->height)
+#define AI_BUFFER_CHANNELS(buf_) ((buf_)->channels)
+#define AI_BUFFER_N_BATCHES(buf_) ((buf_)->n_batches)
+#define AI_BUFFER_DATA(buf_, type_) ((type_*)((buf_)->data))
+
+#define AI_BUFFER_META_INFO(buf_) ((buf_)->meta_info)
+
+#define AI_BUFFER_META_INFO_INTQ(meta_) \
+ ((meta_) && ((meta_)->flags & AI_BUFFER_META_HAS_INTQ_INFO)) ? ((meta_)->intq_info) \
+ : NULL // NOLINT
+
+#define AI_BUFFER_META_INFO_INTQ_GET_SCALE(meta_, pos_) \
+ ((AI_BUFFER_META_INFO_INTQ(meta_)) \
+ ? AI_INTQ_INFO_LIST_SCALE(AI_BUFFER_META_INFO_INTQ(meta_), ai_float, pos_) \
+ : 0)
+
+#define AI_BUFFER_META_INFO_INTQ_GET_ZEROPOINT(meta_, pos_) \
+ ((AI_BUFFER_META_INFO_INTQ(meta_)) \
+ ? ((AI_INTQ_INFO_LIST_FLAGS(AI_BUFFER_META_INFO_INTQ(meta_)) & \
+ AI_BUFFER_META_FLAG_ZEROPOINT_U8) \
+ ? AI_INTQ_INFO_LIST_ZEROPOINT(AI_BUFFER_META_INFO_INTQ(meta_), ai_u8, pos_) \
+ : AI_INTQ_INFO_LIST_ZEROPOINT(AI_BUFFER_META_INFO_INTQ(meta_), ai_i8, pos_)) \
+ : 0)
+
+#define AI_BUFFER_META_INFO_INIT(flags_, intq_info_) \
Review comment:
nit: can't see where this is used
##########
File path: src/runtime/crt/contrib/stm32/ai_runtime_api.h
##########
@@ -0,0 +1,226 @@
+/*
+ * 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.
+ */
+
+/*!
+ * \file ai_runtime_api.h
+ * \brief The runtime API for the TVM generated C code.
+ */
+
+#ifndef TVM_RUNTIME_CRT_CONTRIB_STM32_AI_RUNTIME_API_H_
+#define TVM_RUNTIME_CRT_CONTRIB_STM32_AI_RUNTIME_API_H_
+
+#include "ai_platform.h"
+#include "dlpack/dlpack.h" // From TVM
+#include "tvm/runtime/c_runtime_api.h" // From TVM
+
+//
+// This describes current ai_runtime version
+//
+#define AI_PLATFORM_RUNTIME_MAJOR 1
+#define AI_PLATFORM_RUNTIME_MINOR 0
+#define AI_PLATFORM_RUNTIME_MICRO 0
+
+#define AI_STATIC static
+
+#if defined(_MSC_VER)
+#define AI_INLINE __inline
+#elif defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
+#define AI_INLINE inline
+#elif defined(__CC_ARM)
+#define AI_INLINE __inline
+/* Keil disallows anonymous union initialization by default */
+#pragma anon_unions
+#elif defined(__GNUC__)
+#define AI_INLINE __inline
+#else
+/* Dynamic libraries are not supported by the compiler */
+#endif
+
+/*********************************************************/
+
+typedef uint8_t* ai_ptr;
+
+typedef enum { AI_STATUS_OK = 0, AI_STATUS_ERROR = 1, AI_STATUS_DELEGATE_ERROR = 2 } ai_status;
+
+// =======================================================
+// ai_quantization_info
+//
+// Parameters for asymmetric quantization across a dimension (i.e
+// per output channel quantization).
+// quantized_dimension specifies which dimension the scales and
+// zero_points correspond to.
+// For a particular value in quantized_dimension, quantized values
+// can be converted back to float using:
+// real_value = scale * (quantized_value - zero_point)
+// =======================================================
+
+typedef struct {
+ /*!
+ * \brief The quantization info, if quantized
+ */
+ float* scale;
+ int32_t* zero_point;
+ int32_t dim;
+} ai_quantization_info;
+
+// =======================================================
+// ai_tensor
+// =======================================================
+
+typedef struct {
+ /*!
+ * \brief The TVM tensor.
+ */
+ DLTensor dltensor;
+ /*!
+ * \brief The quantization info, if quantized
+ */
+ ai_quantization_info* quant;
+} ai_tensor;
+
+// =======================================================
+// get_dltensor
+// =======================================================
+AI_STATIC AI_INLINE DLTensor* get_dltensor(ai_tensor* tensor) { return &tensor->dltensor; }
+
+// =======================================================
+// get_tensor_elts
+// =======================================================
+AI_STATIC AI_INLINE uint32_t get_tensor_elts(const ai_tensor* tensor) {
+ const DLTensor* t = &tensor->dltensor;
+ uint32_t elts = 1;
+ for (int i = 0; i < t->ndim; ++i) {
+ elts *= t->shape[i];
+ }
+ return elts;
+}
+
+// =======================================================
+// get_tensor_size
+// =======================================================
+AI_STATIC AI_INLINE uint32_t get_tensor_size(const ai_tensor* tensor) {
+ const DLTensor* t = &tensor->dltensor;
+ uint32_t size = 1;
+ for (int i = 0; i < t->ndim; ++i) {
+ size *= t->shape[i];
+ }
+ size *= (t->dtype.bits * t->dtype.lanes + 7) / 8;
+ return size;
+}
+
+// =======================================================
+// ai_network_info
+// =======================================================
+
+typedef struct {
+ const char* name;
+ const char* datetime;
+ const char* revision;
+ const char* tool_version;
+ const char* api_version;
+ uint16_t n_nodes;
+ uint8_t n_inputs;
+ uint8_t n_outputs;
+ uint32_t activations_size;
+ uint32_t params_size;
+ ai_ptr activations;
+ ai_tensor** inputs;
+ ai_tensor** outputs;
+ const ai_ptr (*ai_get_params)(void);
+ ai_status (*ai_create)(const ai_ptr weights, const ai_ptr activations);
+ ai_status (*ai_destroy)();
+ ai_status (*ai_run)(ai_tensor* input[], ai_tensor* output[]);
+} ai_model_info;
+
+#define AI_MODEL_name(x) (x->name)
+#define AI_MODEL_datetime(x) (x->datetime)
+#define AI_MODEL_revision(x) (x->revision)
+#define AI_MODEL_tool_version(x) (x->tool_version)
+#define AI_MODEL_api_version(x) (x->api_version)
+#define AI_MODEL_n_nodes(x) (x->n_nodes)
+#define AI_MODEL_n_inputs(x) (x->n_inputs)
+#define AI_MODEL_n_outputs(x) (x->n_outputs)
+#define AI_MODEL_activations_size(x) (x->activations_size)
+#define AI_MODEL_params_size(x) (x->params_size)
+#define AI_MODEL_inputs(x) (x->inputs)
+#define AI_MODEL_outputs(x) (x->outputs)
+#define AI_MODEL_activations(x) (x->activations)
+
+// =======================================================
+// Iterator
Review comment:
could you add a test to exercise these functions?
##########
File path: python/tvm/contrib/stm32/BaseEmitter.py
##########
@@ -0,0 +1,1257 @@
+# 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.
+
+# pylint: disable=line-too-long
+
+"""Code emission for the STM32 targets."""
+
+import json
+import os
+import re
+import tarfile
+
+from datetime import datetime
+
+import numpy as np
+
+import tvm
+from tvm.contrib import utils
+
+AI_TOOLS_VERSION_MAJOR = 1
+AI_TOOLS_VERSION_MINOR = 8
+AI_TOOLS_VERSION_MICRO = 0
+
+AI_API_VERSION_MAJOR = 1
+AI_API_VERSION_MINOR = 0
+AI_API_VERSION_MICRO = 0
+
+AI_TOOLS_REVISION = "v1"
+
+DBAR = "=" * 60
+
+
+def _fix_name(node_name):
+ """Replace ':' with '_' in names like 'InputImg:0'"""
+ return node_name.replace(":", "_")
+
+
+def get_input_tensor_name(node_name):
+ return _fix_name(node_name)
+
+
+def get_output_tensor_name(node_name, idx):
+ return _fix_name(node_name) + "_" + str(idx)
+
+
+def get_tensor_data_name(tensor_name):
+ return tensor_name + ".dltensor.data"
+
+
+def get_node_args_name(node_name):
+ return _fix_name(node_name) + "_args"
+
+
+def get_node_arg_types_name(node_name):
+ return _fix_name(node_name) + "_arg_type_ids"
+
+
+def _get_type_size(dltype):
+
+ if dltype in ("uint64", "int64"):
+ return 8
+ if dltype in ("uint32", "int32", "float32"):
+ return 4
+ if dltype in ("uint16", "int16"):
+ return 2
+ if dltype in ("uint8", "int8"):
+ return 1
+
+ raise ValueError(f"Data type {dltype} is not supported")
+
+
+def _get_type_data(dltype):
+
+ if dltype == "uint64":
Review comment:
suggest to use a python dict for this:
```
C_TYPE_BY_DLTYPE = {
"uint64": "kDLUinit, 64, 1",
# ...
}
```
and
```
try:
return C_TYPE_BY_DLTYPE[dltype]
except KeyError:
raise ValueError(f"Data type {dltype} is not supported")
```
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org