Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[microTVM] Project API Arduino support #8708

Merged
merged 11 commits into from
Aug 18, 2021
Merged
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
30 changes: 30 additions & 0 deletions apps/microtvm/arduino/example_project/project.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* 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.
*/

#include "src/model.h"

void setup() {
TVMInitialize();
// If desired, initialize the RNG with random noise
// randomSeed(analogRead(0));
}

void loop() {
//TVMExecute(input_data, output_data);
}
94 changes: 94 additions & 0 deletions apps/microtvm/arduino/example_project/src/model.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/*
* 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.
*/

#include "model.h"

#include "Arduino.h"
#include "standalone_crt/include/tvm/runtime/crt/internal/aot_executor/aot_executor.h"
#include "standalone_crt/include/tvm/runtime/crt/stack_allocator.h"

// AOT memory array
static uint8_t g_aot_memory[WORKSPACE_SIZE];
extern tvm_model_t tvmgen_default_network;
tvm_workspace_t app_workspace;

// Blink code for debugging purposes
void TVMPlatformAbort(tvm_crt_error_t error) {
TVMLogf("TVMPlatformAbort: 0x%08x\n", error);
for (;;) {
#ifdef LED_BUILTIN
guberti marked this conversation as resolved.
Show resolved Hide resolved
digitalWrite(LED_BUILTIN, HIGH);
delay(250);
digitalWrite(LED_BUILTIN, LOW);
delay(250);
digitalWrite(LED_BUILTIN, HIGH);
delay(250);
digitalWrite(LED_BUILTIN, LOW);
delay(750);
#endif
}
}

void TVMLogf(const char* msg, ...) {}

tvm_crt_error_t TVMPlatformMemoryAllocate(size_t num_bytes, DLDevice dev, void** out_ptr) {
return StackMemoryManager_Allocate(&app_workspace, num_bytes, out_ptr);
}

tvm_crt_error_t TVMPlatformMemoryFree(void* ptr, DLDevice dev) {
return StackMemoryManager_Free(&app_workspace, ptr);
}

unsigned long g_utvm_start_time_micros;
int g_utvm_timer_running = 0;

tvm_crt_error_t TVMPlatformTimerStart() {
if (g_utvm_timer_running) {
return kTvmErrorPlatformTimerBadState;
}
g_utvm_timer_running = 1;
g_utvm_start_time_micros = micros();
return kTvmErrorNoError;
}

tvm_crt_error_t TVMPlatformTimerStop(double* elapsed_time_seconds) {
if (!g_utvm_timer_running) {
return kTvmErrorPlatformTimerBadState;
}
g_utvm_timer_running = 0;
unsigned long g_utvm_stop_time = micros() - g_utvm_start_time_micros;
*elapsed_time_seconds = ((double)g_utvm_stop_time) / 1e6;
return kTvmErrorNoError;
}

tvm_crt_error_t TVMPlatformGenerateRandom(uint8_t* buffer, size_t num_bytes) {
for (size_t i = 0; i < num_bytes; i++) {
buffer[i] = rand();
}
return kTvmErrorNoError;
}

void TVMInitialize() { StackMemoryManager_Init(&app_workspace, g_aot_memory, WORKSPACE_SIZE); }

void TVMExecute(void* input_data, void* output_data) {
int ret_val = tvmgen_default_run_model(input_data, output_data);
if (ret_val != 0) {
TVMPlatformAbort(kTvmErrorPlatformCheckFailure);
}
}
40 changes: 40 additions & 0 deletions apps/microtvm/arduino/example_project/src/model.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* 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.
*/

#define WORKSPACE_SIZE $workspace_size_bytes

#ifdef __cplusplus
extern "C" {
#endif

void TVMInitialize();

/* TODO template this function signature with the input and output
* data types and sizes. For example:
*
* void TVMExecute(uint8_t input_data[9216], uint8_t output_data[3]);
*
* Note this can only be done once MLF has JSON metadata describing
* inputs and outputs.
*/
void TVMExecute(void* input_data, void* output_data);

#ifdef __cplusplus
} // extern "C"
#endif
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* 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.
*/

/*!
* \brief CRT configuration for the host-linked CRT.
*/
#ifndef TVM_RUNTIME_MICRO_CRT_CONFIG_H_
#define TVM_RUNTIME_MICRO_CRT_CONFIG_H_

/*! Log level of the CRT runtime */
#define TVM_CRT_LOG_LEVEL TVM_CRT_LOG_LEVEL_DEBUG

/*! Support low-level debugging in MISRA-C runtime */
#define TVM_CRT_DEBUG 0

/*! Maximum supported dimension in NDArray */
#define TVM_CRT_MAX_NDIM 6
/*! Maximum supported arguments in generated functions */
#define TVM_CRT_MAX_ARGS 10
/*! Maximum supported string length in dltype, e.g. "int8", "int16", "float32" */
#define TVM_CRT_MAX_STRLEN_DLTYPE 10
/*! Maximum supported string length in function names */
#define TVM_CRT_MAX_STRLEN_FUNCTION_NAME 80

/*! Maximum number of registered modules. */
#define TVM_CRT_MAX_REGISTERED_MODULES 2

/*! Size of the global function registry, in bytes. */
#define TVM_CRT_GLOBAL_FUNC_REGISTRY_SIZE_BYTES 512

/*! Maximum packet size, in bytes, including the length header. */
#define TVM_CRT_MAX_PACKET_SIZE_BYTES 8 * 1024

/*! \brief Maximum length of a PackedFunc function name. */
#define TVM_CRT_MAX_FUNCTION_NAME_LENGTH_BYTES 30

// #define TVM_CRT_FRAMER_ENABLE_LOGS

#endif // TVM_RUNTIME_MICRO_CRT_CONFIG_H_
53 changes: 53 additions & 0 deletions apps/microtvm/arduino/host_driven/project.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
* 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.
*/

#include "src/standalone_crt/include/tvm/runtime/crt/microtvm_rpc_server.h"
#include "src/standalone_crt/include/tvm/runtime/crt/logging.h"
microtvm_rpc_server_t server;

// Called by TVM to write serial data to the UART.
ssize_t write_serial(void* unused_context, const uint8_t* data, size_t size) {
Serial.write(data, size);
return size;
}

void setup() {
server = MicroTVMRpcServerInit(write_serial, NULL);
TVMLogf("microTVM Arduino runtime - running");
Serial.begin(115200);
guberti marked this conversation as resolved.
Show resolved Hide resolved

// If desired, initialize the RNG with random noise
// randomSeed(analogRead(0));
}

void loop() {
// Read at most 128 bytes at a time to prevent stack blowup
int to_read = min(Serial.available(), 128);

uint8_t data[to_read];
size_t bytes_remaining = Serial.readBytes((char*) data, to_read);
uint8_t* arr_ptr = data;
while (bytes_remaining > 0) {
// Pass the received bytes to the RPC server.
tvm_crt_error_t err = MicroTVMRpcServerLoop(server, &arr_ptr, &bytes_remaining);
if (err != kTvmErrorNoError && err != kTvmErrorFramingShortPacket) {
TVMPlatformAbort(err);
}
}
}
75 changes: 75 additions & 0 deletions apps/microtvm/arduino/host_driven/src/model_support.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
* 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.
*/

#include "standalone_crt/include/tvm/runtime/crt/internal/aot_executor/aot_executor.h"
#include "stdarg.h"

// Blink code for debugging purposes
void TVMPlatformAbort(tvm_crt_error_t error) {
TVMLogf("TVMPlatformAbort: 0x%08x\n", error);
for (;;)
;
}

size_t TVMPlatformFormatMessage(char* out_buf, size_t out_buf_size_bytes, const char* fmt,
va_list args) {
return vsnprintf(out_buf, out_buf_size_bytes, fmt, args);
}

tvm_crt_error_t TVMPlatformMemoryAllocate(size_t num_bytes, DLDevice dev, void** out_ptr) {
if (num_bytes == 0) {
num_bytes = sizeof(int);
}
*out_ptr = malloc(num_bytes);
return (*out_ptr == NULL) ? kTvmErrorPlatformNoMemory : kTvmErrorNoError;
}

tvm_crt_error_t TVMPlatformMemoryFree(void* ptr, DLDevice dev) {
free(ptr);
return kTvmErrorNoError;
}

unsigned long g_utvm_start_time_micros;
int g_utvm_timer_running = 0;

tvm_crt_error_t TVMPlatformTimerStart() {
if (g_utvm_timer_running) {
return kTvmErrorPlatformTimerBadState;
}
g_utvm_timer_running = 1;
g_utvm_start_time_micros = micros();
return kTvmErrorNoError;
}

tvm_crt_error_t TVMPlatformTimerStop(double* elapsed_time_seconds) {
if (!g_utvm_timer_running) {
return kTvmErrorPlatformTimerBadState;
}
g_utvm_timer_running = 0;
unsigned long g_utvm_stop_time = micros() - g_utvm_start_time_micros;
*elapsed_time_seconds = ((double)g_utvm_stop_time) / 1e6;
return kTvmErrorNoError;
}

tvm_crt_error_t TVMPlatformGenerateRandom(uint8_t* buffer, size_t num_bytes) {
for (size_t i = 0; i < num_bytes; i++) {
buffer[i] = rand();
}
return kTvmErrorNoError;
}
Loading