K210code using kmodel file instead of C file

master
bj-wanghz 2019-04-24 14:36:29 +08:00
parent d80f0d2ac2
commit b1e680f1a0
6 changed files with 353 additions and 80778 deletions

View File

@ -1,23 +1,23 @@
### *pb* file to C file
### *pb* file to *kmodel* file
Download [nncase](https://github.com/kendryte/nncase) tool and uncompress it. You'll get `ncc` directory.
Make a directory named `ncc`. Download [nncase](<https://github.com/kendryte/nncase/releases>) tool and uncompress it to `ncc`.
#### *pb* file to tflite
Copy the pretrained model `mobilenetv1_1.0.pb` in `pretrained` directory to `ncc\bin`. Rename it to `mobilenetv1.pb` to avoid the function name error in the following steps.
Copy the pretrained model `mobilenetv1_1.0.pb` in `pretrained` directory to `ncc\bin`.
Enter `ncc\bin` directory from *cmd*.
Enter `ncc\bin` directory.
```shell
.\toco.exe --input_file=mobilenetv1.pb --input_format=TENSORFLOW_GRAPHDEF --output_file=mobilenetv1.tflite --output_format=TFLITE --input_shape=1,224,224,3 --input_array=inputs --output_array=MobileNetV1/Bottleneck2/BatchNorm/Reshape_1 --inference=FLOAT
./toco --input_file=mobilenetv1_1.0.pb --input_format=TENSORFLOW_GRAPHDEF --output_file=mobilenetv1_1.0.tflite --output_format=TFLITE --input_shape=1,224,224,3 --input_array=inputs --output_array=MobileNetV1/Bottleneck2/BatchNorm/Reshape_1 --inference=FLOAT
```
#### tflite to C code
#### tflite to kmodel
Enter `ncc` directory and place the dataset into `ncc\dataset` directory.
```shell
.\ncc.exe -i tflite -o k210code --dataset .\dataset\ .\bin\mobilenetv1.tflite .\bin\mobilenetv1.c
./ncc -i tflite -o k210model --dataset ./dataset ./bin/mobilenetv1_1.0.tflite ./bin/mobilenetv1_1.0.kmodel
```
### Prepare image for test

315
K210code/incbin.h Normal file
View File

@ -0,0 +1,315 @@
/**
* @file incbin.h
* @author Dale Weiler
* @brief Utility for including binary files
*
* Facilities for including binary files into the current translation unit and
* making use from them externally in other translation units.
*/
#ifndef INCBIN_HDR
#define INCBIN_HDR
#include <limits.h>
# define INCBIN_ALIGNMENT_INDEX 8
/* Lookup table of (1 << n) where `n' is `INCBIN_ALIGNMENT_INDEX' */
#define INCBIN_ALIGN_SHIFT_0 1
#define INCBIN_ALIGN_SHIFT_1 2
#define INCBIN_ALIGN_SHIFT_2 4
#define INCBIN_ALIGN_SHIFT_3 8
#define INCBIN_ALIGN_SHIFT_4 16
#define INCBIN_ALIGN_SHIFT_5 32
#define INCBIN_ALIGN_SHIFT_6 64
#define INCBIN_ALIGN_SHIFT_7 128
#define INCBIN_ALIGN_SHIFT_8 256
/* Actual alignment value */
#define INCBIN_ALIGNMENT \
INCBIN_CONCATENATE( \
INCBIN_CONCATENATE(INCBIN_ALIGN_SHIFT, _), \
INCBIN_ALIGNMENT_INDEX)
/* Stringize */
#define INCBIN_STR(X) \
#X
#define INCBIN_STRINGIZE(X) \
INCBIN_STR(X)
/* Concatenate */
#define INCBIN_CAT(X, Y) \
X ## Y
#define INCBIN_CONCATENATE(X, Y) \
INCBIN_CAT(X, Y)
/* Deferred macro expansion */
#define INCBIN_EVAL(X) \
X
#define INCBIN_INVOKE(N, ...) \
INCBIN_EVAL(N(__VA_ARGS__))
/* Green Hills uses a different directive for including binary data */
#if defined(__ghs__)
# define INCBIN_MACRO "\tINCBIN"
#else
# define INCBIN_MACRO ".incbin"
#endif
#ifndef _MSC_VER
# define INCBIN_ALIGN \
__attribute__((aligned(INCBIN_ALIGNMENT)))
#else
# define INCBIN_ALIGN __declspec(align(INCBIN_ALIGNMENT))
#endif
#if defined(__arm__) || /* GNU C and RealView */ \
defined(__arm) || /* Diab */ \
defined(_ARM) /* ImageCraft */
# define INCBIN_ARM
#endif
#ifdef __GNUC__
/* Utilize .balign where supported */
# define INCBIN_ALIGN_HOST ".balign " INCBIN_STRINGIZE(INCBIN_ALIGNMENT) "\n"
# define INCBIN_ALIGN_BYTE ".balign 1\n"
#elif defined(INCBIN_ARM)
/*
* On arm assemblers, the alignment value is calculated as (1 << n) where `n' is
* the shift count. This is the value passed to `.align'
*/
# define INCBIN_ALIGN_HOST ".align" INCBIN_STRINGIZE(INCBIN_ALIGNMENT_INDEX) "\n"
# define INCBIN_ALIGN_BYTE ".align 0\n"
#else
/* We assume other inline assembler's treat `.align' as `.balign' */
# define INCBIN_ALIGN_HOST ".align" INCBIN_STRINGIZE(INCBIN_ALIGNMENT) "\n"
# define INCBIN_ALIGN_BYTE ".align 1\n"
#endif
/* INCBIN_CONST is used by incbin.c generated files */
#if defined(__cplusplus)
# define INCBIN_EXTERNAL extern "C"
# define INCBIN_CONST extern const
#else
# define INCBIN_EXTERNAL extern
# define INCBIN_CONST const
#endif
#if defined(__APPLE__)
/* The directives are different for Apple branded compilers */
# define INCBIN_SECTION ".data\n"
# define INCBIN_GLOBAL(NAME) ".globl " INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME "\n"
# define INCBIN_INT ".long "
# define INCBIN_MANGLE "_"
# define INCBIN_BYTE ".byte "
# define INCBIN_TYPE(...)
#else
# define INCBIN_SECTION ".section .data\n"
# define INCBIN_GLOBAL(NAME) ".global " INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME "\n"
# define INCBIN_INT ".int "
# if defined(__USER_LABEL_PREFIX__)
# define INCBIN_MANGLE INCBIN_STRINGIZE(__USER_LABEL_PREFIX__)
# else
# define INCBIN_MANGLE ""
# endif
# if defined(INCBIN_ARM)
/* On arm assemblers, `@' is used as a line comment token */
# define INCBIN_TYPE(NAME) ".type " INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME ", %object\n"
# elif defined(__MINGW32__) || defined(__MINGW64__)
/* Mingw doesn't support this directive either */
# define INCBIN_TYPE(NAME)
# else
/* It's safe to use `@' on other architectures */
# define INCBIN_TYPE(NAME) ".type " INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME ", @object\n"
# endif
# define INCBIN_BYTE ".byte "
#endif
/* List of style types used for symbol names */
#define INCBIN_STYLE_CAMEL 0
#define INCBIN_STYLE_SNAKE 1
/**
* @brief Specify the prefix to use for symbol names.
*
* By default this is `g', producing symbols of the form:
* @code
* #include "incbin.h"
* INCBIN(Foo, "foo.txt");
*
* // Now you have the following symbols:
* // const unsigned char gFooData[];
* // const unsigned char gFooEnd;
* // const unsigned int gFooSize;
* @endcode
*
* If however you specify a prefix before including: e.g:
* @code
* #define INCBIN_PREFIX incbin
* #include "incbin.h"
* INCBIN(Foo, "foo.txt");
*
* // Now you have the following symbols instead:
* // const unsigned char incbinFooData[];
* // const unsigned char incbinFooEnd;
* // const unsigned int incbinFooSize;
* @endcode
*/
#if !defined(INCBIN_PREFIX)
# define INCBIN_PREFIX g
#endif
/**
* @brief Specify the style used for symbol names.
*
* Possible options are
* - INCBIN_STYLE_CAMEL "CamelCase"
* - INCBIN_STYLE_SNAKE "snake_case"
*
* Default option is *INCBIN_STYLE_CAMEL* producing symbols of the form:
* @code
* #include "incbin.h"
* INCBIN(Foo, "foo.txt");
*
* // Now you have the following symbols:
* // const unsigned char <prefix>FooData[];
* // const unsigned char <prefix>FooEnd;
* // const unsigned int <prefix>FooSize;
* @endcode
*
* If however you specify a style before including: e.g:
* @code
* #define INCBIN_STYLE INCBIN_STYLE_SNAKE
* #include "incbin.h"
* INCBIN(foo, "foo.txt");
*
* // Now you have the following symbols:
* // const unsigned char <prefix>foo_data[];
* // const unsigned char <prefix>foo_end;
* // const unsigned int <prefix>foo_size;
* @endcode
*/
#if !defined(INCBIN_STYLE)
# define INCBIN_STYLE INCBIN_STYLE_CAMEL
#endif
/* Style lookup tables */
#define INCBIN_STYLE_0_DATA Data
#define INCBIN_STYLE_0_END End
#define INCBIN_STYLE_0_SIZE Size
#define INCBIN_STYLE_1_DATA _data
#define INCBIN_STYLE_1_END _end
#define INCBIN_STYLE_1_SIZE _size
/* Style lookup: returning identifier */
#define INCBIN_STYLE_IDENT(TYPE) \
INCBIN_CONCATENATE( \
INCBIN_STYLE_, \
INCBIN_CONCATENATE( \
INCBIN_EVAL(INCBIN_STYLE), \
INCBIN_CONCATENATE(_, TYPE)))
/* Style lookup: returning string literal */
#define INCBIN_STYLE_STRING(TYPE) \
INCBIN_STRINGIZE( \
INCBIN_STYLE_IDENT(TYPE)) \
/* Generate the global labels by indirectly invoking the macro with our style
* type and concatenating the name against them. */
#define INCBIN_GLOBAL_LABELS(NAME, TYPE) \
INCBIN_INVOKE( \
INCBIN_GLOBAL, \
INCBIN_CONCATENATE( \
NAME, \
INCBIN_INVOKE( \
INCBIN_STYLE_IDENT, \
TYPE))) \
INCBIN_INVOKE( \
INCBIN_TYPE, \
INCBIN_CONCATENATE( \
NAME, \
INCBIN_INVOKE( \
INCBIN_STYLE_IDENT, \
TYPE)))
/**
* @brief Externally reference binary data included in another translation unit.
*
* Produces three external symbols that reference the binary data included in
* another translation unit.
*
* The symbol names are a concatenation of `INCBIN_PREFIX' before *NAME*; with
* "Data", as well as "End" and "Size" after. An example is provided below.
*
* @param NAME The name given for the binary data
*
* @code
* INCBIN_EXTERN(Foo);
*
* // Now you have the following symbols:
* // extern const unsigned char <prefix>FooData[];
* // extern const unsigned char <prefix>FooEnd;
* // extern const unsigned int <prefix>FooSize;
* @endcode
*/
#define INCBIN_EXTERN(NAME) \
INCBIN_EXTERNAL INCBIN_ALIGN unsigned char \
INCBIN_CONCATENATE( \
INCBIN_CONCATENATE(INCBIN_PREFIX, NAME), \
INCBIN_STYLE_IDENT(DATA))[]; \
INCBIN_EXTERNAL INCBIN_ALIGN unsigned char * \
INCBIN_CONCATENATE( \
INCBIN_CONCATENATE(INCBIN_PREFIX, NAME), \
INCBIN_STYLE_IDENT(END)); \
INCBIN_EXTERNAL unsigned int \
INCBIN_CONCATENATE( \
INCBIN_CONCATENATE(INCBIN_PREFIX, NAME), \
INCBIN_STYLE_IDENT(SIZE))
/**
* @brief Include a binary file into the current translation unit.
*
* Includes a binary file into the current translation unit, producing three symbols
* for objects that encode the data and size respectively.
*
* The symbol names are a concatenation of `INCBIN_PREFIX' before *NAME*; with
* "Data", as well as "End" and "Size" after. An example is provided below.
*
* @param NAME The name to associate with this binary data (as an identifier.)
* @param FILENAME The file to include (as a string literal.)
*
* @code
* INCBIN(Icon, "icon.png");
*
* // Now you have the following symbols:
* // const unsigned char <prefix>IconData[];
* // const unsigned char <prefix>IconEnd;
* // const unsigned int <prefix>IconSize;
* @endcode
*
* @warning This must be used in global scope
* @warning The identifiers may be different if INCBIN_STYLE is not default
*
* To externally reference the data included by this in another translation unit
* please @see INCBIN_EXTERN.
*/
#ifdef _MSC_VER
#define INCBIN(NAME, FILENAME) \
INCBIN_EXTERN(NAME)
#else
#define INCBIN(NAME, FILENAME) \
__asm__(INCBIN_SECTION \
INCBIN_GLOBAL_LABELS(NAME, DATA) \
INCBIN_ALIGN_HOST \
INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME INCBIN_STYLE_STRING(DATA) ":\n" \
INCBIN_MACRO " \"" FILENAME "\"\n" \
INCBIN_GLOBAL_LABELS(NAME, END) \
INCBIN_ALIGN_BYTE \
INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME INCBIN_STYLE_STRING(END) ":\n" \
INCBIN_BYTE "1\n" \
INCBIN_GLOBAL_LABELS(NAME, SIZE) \
INCBIN_ALIGN_HOST \
INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME INCBIN_STYLE_STRING(SIZE) ":\n" \
INCBIN_INT INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME INCBIN_STYLE_STRING(END) " - " \
INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME INCBIN_STYLE_STRING(DATA) "\n" \
); \
INCBIN_EXTERN(NAME)
#endif
#endif

View File

@ -13,29 +13,24 @@
* limitations under the License.
*/
#include <stdio.h>
#include "kpu.h"
#include <platform.h>
#include <printf.h>
#include <string.h>
#include <stdlib.h>
#include <sysctl.h>
#include "uarths.h"
#include "mobilenetv1.h"
#include "kpu.h"
#include "incbin.h"
#define INCBIN_STYLE INCBIN_STYLE_SNAKE
#define INCBIN_PREFIX
#define PLL0_OUTPUT_FREQ 800000000UL
#define PLL1_OUTPUT_FREQ 300000000UL
INCBIN(model, "mobilenetv1_1.0.kmodel");
kpu_model_context_t task;
volatile uint32_t g_ai_done_flag;
#define IN_SIZE 224
#define OUT_SIZE 7 * 7 * 1024
#define FEATURE_SIZE 1000
volatile uint32_t g_cnt_layer;
uint8_t g_kpu_outbuf[OUT_SIZE] __attribute__((aligned(128)));
float features[FEATURE_SIZE];
extern const unsigned char gImage_image[] __attribute__((aligned(128)));
kpu_task_t task;
static int ai_done(void *ctx)
{
@ -43,71 +38,35 @@ static int ai_done(void *ctx)
return 0;
}
int ai_step(void *ctx)
{
switch (g_cnt_layer)
{
case 0 ... 25:
kpu_conv2d(task.layers + g_cnt_layer);
break;
case 26:
kpu_conv2d_output(task.layers + g_cnt_layer, 5, g_kpu_outbuf, ai_step, NULL);
break;
case 27:
{
quantize_param_t q1 = { .scale = 0.0163548170351515,.bias = 0 }, q2 = { .scale = 0.0021889562700309,.bias = 0 };
kpu_global_average_pool(g_kpu_outbuf, &q1, 7*7, 1024, AI_IO_BASE_ADDR + task.layers[g_cnt_layer].image_addr.data.image_src_addr * 64, &q2);
kpu_matmul_begin(task.layers + g_cnt_layer, 5, (uint64_t *)g_kpu_outbuf, ai_done, NULL);
break;
}
default:
printf("Unexpcted.\n");
while (1);
break;
}
printf("%d\n", g_cnt_layer);
g_cnt_layer++;
return 0;
}
int main()
{
/* Set CPU and dvp clk */
/* Set CPU and KPU clk */
sysctl_pll_set_freq(SYSCTL_PLL0, PLL0_OUTPUT_FREQ);
sysctl_pll_set_freq(SYSCTL_PLL1, PLL1_OUTPUT_FREQ);
sysctl_clock_enable(SYSCTL_CLOCK_AI);
uarths_init();
plic_init();
sysctl_enable_irq();
kpu_task_mobilenetv1_init(&task);
size_t j;
for (j = 0; j < 1; j++)
{
g_cnt_layer = 0;
g_ai_done_flag = 0;
kpu_init(task.eight_bit_mode, ai_step, NULL);
/* start to calculate */
uint64_t t1 = sysctl_get_time_us();
kpu_input_with_padding(task.layers, gImage_image, IN_SIZE, IN_SIZE, 3);
sysctl_disable_irq();
ai_step(NULL);
sysctl_enable_irq();
while (!g_ai_done_flag){}
quantize_param_t q = { .scale = task.output_scale,.bias = task.output_bias };
kpu_matmul_end(g_kpu_outbuf, FEATURE_SIZE, features, &q);
t1 = sysctl_get_time_us() - t1;
printf("takes %f ms\n", t1 / 1000.0);
size_t i;
for (i = 0; i < FEATURE_SIZE; i++)
printf("%f, ", features[i]);
printf("done\n");
if (kpu_load_kmodel(&task, model_data) != 0)
{
printf("\nmodel init error\n");
return -1;
}
while (1)
;
sysctl_enable_irq();
printf("System Start\n");
g_ai_done_flag = 0;
kpu_run_kmodel(&task, gImage_image, DMAC_CHANNEL5, ai_done, NULL);
while (g_ai_done_flag == 0);
float *output;
size_t output_size;
kpu_get_output(&task, 0, (uint8_t **)&output, &output_size);
for (uint32_t i = 0; i < output_size / (sizeof(float)); i++)
printf("%f ", output[i]);
printf("\ndone\n");
while (1);
}

File diff suppressed because it is too large Load Diff

View File

@ -1,2 +0,0 @@
void kpu_task_mobilenetv1_init(kpu_task_t* task);

Binary file not shown.