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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions src/emlearn_cnn_fp32/emlearn_cnn_fp32.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/*
* emlearn_cnn_fp32 wrapper
* This file includes fp32/tm_port.h directly before including mod_cnn.c
* We need to modify mod_cnn.c to not include tm_port.h when CONFIG is already defined
*/

/* Define CONFIG_FP32 first */
#define CONFIG_FP32

// for external module we need static
#define TM_STATIC static

/* Include the fp32 tm_port.h directly */
#include "../tinymaix_cnn/fp32/tm_port.h"

/* Now include mod_cnn.c - it will see CONFIG_FP32 is defined and use fp32/tm_port.h */
#include "../tinymaix_cnn/mod_cnn.c"
6 changes: 6 additions & 0 deletions src/emlearn_cnn_fp32/emlearn_cnn_fp32.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# emlearn_cnn_fp32 - wrapper for frozen unix build
# Imports the native C module compiled with fp32 configuration
try:
from emlearn_cnn_fp32_native import *
except ImportError:
pass
16 changes: 16 additions & 0 deletions src/emlearn_cnn_fp32/micropython.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# emlearn_cnn_fp32 wrapper for Unix port
# This wrapper sets CONFIG_FP32 before including mod_cnn.c

CNN_SRC := $(USERMOD_DIR)/../tinymaix_cnn

# Add wrapper C file which defines CONFIG_FP32
SRC_USERMOD_C += $(USERMOD_DIR)/emlearn_cnn_fp32.c

# Include paths - config directory first to ensure correct tm_port.h is found
CFLAGS_USERMOD += -I$(CNN_SRC)/fp32
CFLAGS_USERMOD += -I$(CNN_SRC)/int8
CFLAGS_USERMOD += -I$(CNN_SRC)/../../dependencies/TinyMaix/include
CFLAGS_USERMOD += -I$(CNN_SRC)/../../dependencies/TinyMaix/src

# Compile flags to suppress TinyMaix warnings
CFLAGS_USERMOD += -Wno-error=unused-variable -Wno-error=multichar -Wdouble-promotion
17 changes: 17 additions & 0 deletions src/emlearn_cnn_int8/emlearn_cnn_int8.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/*
* emlearn_cnn_int8 wrapper
* This file includes int8/tm_port.h directly before including mod_cnn.c
* We need to modify mod_cnn.c to not include tm_port.h when CONFIG is already defined
*/

/* Define CONFIG_INT8 first */
#define CONFIG_INT8

// for external module we need static
#define TM_STATIC static

/* Include the int8 tm_port.h directly */
#include "../tinymaix_cnn/int8/tm_port.h"

/* Now include mod_cnn.c - it will see CONFIG_INT8 is defined and use int8/tm_port.h */
#include "../tinymaix_cnn/mod_cnn.c"
6 changes: 6 additions & 0 deletions src/emlearn_cnn_int8/emlearn_cnn_int8.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# emlearn_cnn_int8 - wrapper for frozen unix build
# Imports the native C module compiled with int8 configuration
try:
from emlearn_cnn_int8_native import *
except ImportError:
pass
16 changes: 16 additions & 0 deletions src/emlearn_cnn_int8/micropython.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# emlearn_cnn_int8 wrapper for Unix port
# This wrapper sets CONFIG_INT8 before including mod_cnn.c

CNN_SRC := $(USERMOD_DIR)/../tinymaix_cnn

# Add wrapper C file which defines CONFIG_INT8
SRC_USERMOD_C += $(USERMOD_DIR)/emlearn_cnn_int8.c

# Include paths - config directory first to ensure correct tm_port.h is found
CFLAGS_USERMOD += -I$(CNN_SRC)/int8
CFLAGS_USERMOD += -I$(CNN_SRC)/fp32
CFLAGS_USERMOD += -I$(CNN_SRC)/../../dependencies/TinyMaix/include
CFLAGS_USERMOD += -I$(CNN_SRC)/../../dependencies/TinyMaix/src

# Compile flags to suppress TinyMaix warnings
CFLAGS_USERMOD += -Wno-error=unused-variable -Wno-error=multichar -Wdouble-promotion
2 changes: 2 additions & 0 deletions src/manifest_unix.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
# Ref https://docs.micropython.org/en/latest/reference/manifest.html
module("emlearn_trees.py", base_path='./emlearn_trees')
module("emlearn_kmeans.py", base_path='./emlearn_kmeans')
module("emlearn_cnn_int8.py", base_path='./emlearn_cnn_int8')
module("emlearn_cnn_fp32.py", base_path='./emlearn_cnn_fp32')
module("emlearn_fft.py", base_path='./emlearn_fft')
module("emlearn_linreg.py", base_path='./emlearn_linreg')
module("emlearn_logreg.py", base_path='./emlearn_logreg')
Expand Down
4 changes: 3 additions & 1 deletion src/tinymaix_cnn/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ $(DIST_FILE): $(MOD).mpy $(DIST_DIR)
# Include to get the rules for compiling and linking the module
include $(MPY_DIR)/py/dynruntime.mk

CFLAGS += -I$(CONFIG_DIR) -I$(TINYMAIX_DIR)/include -I$(TINYMAIX_DIR)/src -Wno-error=unused-variable -Wno-error=multichar -Wdouble-promotion
CONFIG_DEFINE = CONFIG_$(shell echo $(CONFIG) | tr '[:lower:]' '[:upper:]')

CFLAGS += -D${CONFIG_DEFINE} -I$(CONFIG_DIR) -I$(TINYMAIX_DIR)/include -I$(TINYMAIX_DIR)/src -Wno-error=unused-variable -Wno-error=multichar -Wdouble-promotion

dist: $(DIST_FILE)
10 changes: 7 additions & 3 deletions src/tinymaix_cnn/fp32/tm_port.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,20 +35,24 @@ limitations under the License.
#define TM_MDL_TYPE TM_MDL_FP32
#define TM_FASTSCALE (0) //enable if your chip don't have FPU, may speed up 1/3, but decrease accuracy
#define TM_LOCAL_MATH (1) //use local math func (like exp()) to avoid libm
#define TM_ENABLE_STAT (1) //enable mdl stat functions
#define TM_ENABLE_STAT (0) //enable mdl stat functions
#define TM_MAX_CSIZE (1000) //max channel num //used if INT8 mdl //cost TM_MAX_CSIZE*4 Byte
#define TM_MAX_KSIZE (5*5) //max kernel_size //cost TM_MAX_KSIZE*4 Byte
#define TM_MAX_KCSIZE (3*3*256) //max kernel_size*channels //cost TM_MAX_KSIZE*sizeof(mtype_t) Byte

#define TM_INLINE __attribute__((always_inline)) static inline
#ifndef TM_WEAK
#define TM_WEAK __attribute__((weak))
#endif

// Disable "static" (non-const) globals, since they are not supported by MicroPython mpy_ld.py
#define TM_STATIC
#ifndef TM_STATIC
#define TM_STATIC
#endif

// Use MicroPython for dynamic allocation
#define tm_malloc(x) m_malloc(x)
#define tm_free(x) mod_cnn_free(x)
#define tm_free(x) CNN_FREE(x)

// FIXME: set theese to use MicroPython primitives

Expand Down
10 changes: 7 additions & 3 deletions src/tinymaix_cnn/int8/tm_port.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,20 +35,24 @@ limitations under the License.
#define TM_MDL_TYPE TM_MDL_INT8
#define TM_FASTSCALE (0) //enable if your chip don't have FPU, may speed up 1/3, but decrease accuracy
#define TM_LOCAL_MATH (1) //use local math func (like exp()) to avoid libm
#define TM_ENABLE_STAT (1) //enable mdl stat functions
#define TM_ENABLE_STAT (0) //enable mdl stat functions
#define TM_MAX_CSIZE (1000) //max channel num //used if INT8 mdl //cost TM_MAX_CSIZE*4 Byte
#define TM_MAX_KSIZE (5*5) //max kernel_size //cost TM_MAX_KSIZE*4 Byte
#define TM_MAX_KCSIZE (3*3*256) //max kernel_size*channels //cost TM_MAX_KSIZE*sizeof(mtype_t) Byte

#define TM_INLINE __attribute__((always_inline)) static inline
#ifndef TM_WEAK
#define TM_WEAK __attribute__((weak))
#endif

// Disable "static" (non-const) globals, since they are not supported by MicroPython mpy_ld.py
#define TM_STATIC
#ifndef TM_STATIC
#define TM_STATIC
#endif

// Use MicroPython for dynamic allocation
#define tm_malloc(x) m_malloc(x)
#define tm_free(x) mod_cnn_free(x)
#define tm_free(x) CNN_FREE(x)

// FIXME: set theese to use MicroPython primitives

Expand Down
75 changes: 54 additions & 21 deletions src/tinymaix_cnn/mod_cnn.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,40 @@
#include "py/runtime.h"
#endif

// Check that only one CONFIG is defined
#if defined(CONFIG_FP32) && defined(CONFIG_INT8)
#error "Only one of CONFIG_FP32 or CONFIG_INT8 should be defined"
#endif

void mod_cnn_free(void *ptr);
// Define unique symbol names based on CONFIG
#ifdef CONFIG_FP32
#define CNN_TYPE mod_cnn_fp32_type
#define CNN_CMODULE mod_cnn_fp32_cmodule
#define CNN_FREE mod_cnn_fp32_free
#elif defined(CONFIG_INT8)
#define CNN_TYPE mod_cnn_int8_type
#define CNN_CMODULE mod_cnn_int8_cmodule
#define CNN_FREE mod_cnn_int8_free
#else
#define CNN_TYPE mod_cnn_int8_type
#define CNN_CMODULE mod_cnn_int8_cmodule
#define CNN_FREE mod_cnn_int8_free
#endif

// TinyMaix config
#include "./tm_port.h"
// Forward declaration for tm_port.h
void CNN_FREE(void *ptr);

// TinyMaix config - include from the config directory
// Only include if not already included by wrapper
#ifndef __TM_PORT_H
#ifdef CONFIG_INT8
#include "./int8/tm_port.h"
#elif defined(CONFIG_FP32)
#include "./fp32/tm_port.h"
#else
#error "No config defined"
#endif
#endif

#include <tinymaix.h>

Expand Down Expand Up @@ -37,7 +66,7 @@ void *memset(void *s, int c, size_t n) {

// get model output shapes
//mdl: model handle; in: input mat; out: output mat
int TM_WEAK tm_get_outputs(tm_mdl_t* mdl, tm_mat_t* out, int out_length)
static int tm_get_outputs(tm_mdl_t* mdl, tm_mat_t* out, int out_length)
{
// NOTE: based on tm_run, but without actually executing
int out_idx = 0;
Expand Down Expand Up @@ -81,18 +110,18 @@ typedef struct _mp_obj_mod_cnn_t {
} mp_obj_mod_cnn_t;

#if MICROPY_ENABLE_DYNRUNTIME
mp_obj_full_type_t mod_cnn_type;
mp_obj_full_type_t CNN_TYPE;
#else
static const mp_obj_type_t mod_cnn_type;
static const mp_obj_type_t CNN_TYPE;
#endif


void mod_cnn_free(void *ptr)
void CNN_FREE(void *ptr)
{
#if MICROPY_ENABLE_DYNRUNTIME
return m_free(ptr);
#else
return m_del(void *, ptr, 0); // XXX: not sure if safe
return m_del(void *, ptr, 0);
#endif
}

Expand All @@ -116,7 +145,7 @@ static mp_obj_t mod_cnn_new(mp_obj_t model_data_obj) {
const int model_data_length = bufinfo.len / sizeof(*model_data_buffer);

// Construct object
mp_obj_mod_cnn_t *o = mp_obj_malloc(mp_obj_mod_cnn_t, (mp_obj_type_t *)&mod_cnn_type);
mp_obj_mod_cnn_t *o = mp_obj_malloc(mp_obj_mod_cnn_t, (mp_obj_type_t *)&CNN_TYPE);
tm_mdl_t *model = &o->model;

// Copy the model data
Expand Down Expand Up @@ -283,15 +312,15 @@ mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *a

mp_store_global(MP_QSTR_new, MP_OBJ_FROM_PTR(&mod_cnn_new_obj));

mod_cnn_type.base.type = (void*)&mp_fun_table.type_type;
mod_cnn_type.flags = MP_TYPE_FLAG_ITER_IS_CUSTOM;
mod_cnn_type.name = MP_QSTR_tinymaixcnn;
CNN_TYPE.base.type = (void*)&mp_fun_table.type_type;
CNN_TYPE.flags = MP_TYPE_FLAG_ITER_IS_CUSTOM;
CNN_TYPE.name = MP_QSTR_tinymaixcnn;
// methods
mod_locals_dict_table[0] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_run), MP_OBJ_FROM_PTR(&mod_cnn_run_obj) };
mod_locals_dict_table[1] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR___del__), MP_OBJ_FROM_PTR(&mod_cnn_del_obj) };
mod_locals_dict_table[2] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_output_dimensions), MP_OBJ_FROM_PTR(&mod_cnn_output_dimensions_obj) };

MP_OBJ_TYPE_SET_SLOT(&mod_cnn_type, locals_dict, (void*)&mod_locals_dict, 2);
MP_OBJ_TYPE_SET_SLOT(&CNN_TYPE, locals_dict, (void*)&mod_locals_dict, 2);

// This must be last, it restores the globals dict
MP_DYNRUNTIME_INIT_EXIT
Expand All @@ -301,14 +330,14 @@ mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *a
// Define a class
static const mp_rom_map_elem_t mod_cnn_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_run), MP_ROM_PTR(&mod_cnn_run_obj) },
{ MP_ROM_QSTR(MP_QSTR_output_dimensions), MP_ROM_PTR(&mod_cnn_del_obj) },
{ MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mod_cnn_output_dimensions_obj) }
{ MP_ROM_QSTR(MP_QSTR_output_dimensions), MP_ROM_PTR(&mod_cnn_output_dimensions_obj) },
{ MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mod_cnn_del_obj) }
};
static MP_DEFINE_CONST_DICT(mod_cnn_locals_dict, mod_cnn_locals_dict_table);


static MP_DEFINE_CONST_OBJ_TYPE(
mod_cnn_type,
CNN_TYPE,
MP_QSTR_tinymaix_cnn,
MP_TYPE_FLAG_NONE,
locals_dict, &mod_cnn_locals_dict
Expand All @@ -320,13 +349,17 @@ static const mp_rom_map_elem_t mod_cnn_globals_table[] = {
};
static MP_DEFINE_CONST_DICT(mod_cnn_globals, mod_cnn_globals_table);

const mp_obj_module_t mod_cnn_cmodule = {
const mp_obj_module_t CNN_CMODULE = {
.base = { &mp_type_module },
.globals = (mp_obj_dict_t *)&mod_cnn_globals,
};

// FIXME: unhardcode config part of module name
MP_REGISTER_MODULE(MP_QSTR_emlearn_cnn_int8, mod_cnn_cmodule);
// Module name depends on CONFIG
#ifdef CONFIG_FP32
MP_REGISTER_MODULE(MP_QSTR_emlearn_cnn_fp32_native, CNN_CMODULE);
#elif defined(CONFIG_INT8)
MP_REGISTER_MODULE(MP_QSTR_emlearn_cnn_int8_native, CNN_CMODULE);
#else
MP_REGISTER_MODULE(MP_QSTR_emlearn_cnn_int8_native, CNN_CMODULE);
#endif
#endif


Loading