ml-models-public: Move model-related code away from sw/vec_iree

Build the workload in the model project

Change-Id: I92f3442d78071113ea4fed86beefd32b3657059c
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..91eb94d
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,29 @@
+cmake_minimum_required(VERSION 3.13.4)
+
+# ------------------------------------------------------------------------------
+# Project configuration
+# ------------------------------------------------------------------------------
+project(ml-models-public)
+
+set_property(GLOBAL PROPERTY USE_FOLDERS ON)
+
+set(SPRINGBOK_IREE_DIR "$ENV{ROOTDIR}/sw/vec_iree" CACHE PATH
+    "Springbok IREE library path (default: $ENV{ROOTDIR}/sw/vec_iree)")
+
+include_directories(BEFORE SYSTEM ${CMAKE_CURRENT_LIST_DIR})
+include_directories(BEFORE SYSTEM ${CMAKE_CURRENT_BINARY_DIR})
+include_directories(BEFORE SYSTEM ${SPRINGBOK_IREE_DIR})
+
+# Include springbok_iree libraries.
+add_subdirectory(${SPRINGBOK_IREE_DIR} springbok_iree)
+
+# Add compilation options.
+include(${SPRINGBOK_IREE_DIR}/cmake/springbok_ops.cmake)
+
+# Set default linker memory size for the whole project.
+set(TCM_LENGTH "16M" CACHE STRING "TCM Length (default: 16M)")
+add_link_options("LINKER:--defsym=__tcm_length__=${TCM_LENGTH}")
+
+# Include model directories.
+add_subdirectory(float_models)
+add_subdirectory(quant_models)
diff --git a/README.md b/README.md
index c584786..2623e78 100644
--- a/README.md
+++ b/README.md
@@ -24,3 +24,9 @@
 
 For tflite models, use the [web-based visualization tool](https://lutzroeder.github.io/netron/) to
 inspect the file. The tool supports drag and drop or file GUI.
+
+## Model executables
+
+For each model, the corresponding model executable under `iree_exec` can be
+built with the .c/.h files using `sw/vec_iree` project as library. They can be
+run as unit tests via lit framework using Renode or QEMU.
diff --git a/float_models/CMakeLists.txt b/float_models/CMakeLists.txt
new file mode 100644
index 0000000..2831e7a
--- /dev/null
+++ b/float_models/CMakeLists.txt
@@ -0,0 +1,148 @@
+# For the generated header files, include the generated directory path.
+# It is against the c-style recommendation, but we want to create a symlink of
+# this directory to ml/ml-models for the internal model zoo so all the models
+# can be built there.
+include_directories(BEFORE SYSTEM ${CMAKE_CURRENT_BINARY_DIR})
+
+#-------------------------------------------------------------------------------
+# Build the mlir bytecode modules with iree-compile. Note the last two flags
+# are for RVV support.
+#-------------------------------------------------------------------------------
+
+springbok_modules(
+  NAME
+    mobilenet_v1
+  SRC
+    "mobilenet_v1_0.25_224_float.tflite"
+  C_IDENTIFIER
+    "float_models_mobilenet_v1"
+  FLAGS
+    "-iree-input-type=tosa"
+    "-riscv-v-vector-bits-min=512"
+    "-riscv-v-fixed-length-vector-lmul-max=8"
+  RVV_OFF
+  PUBLIC
+)
+
+springbok_modules(
+  NAME
+    mnist
+  SRC
+    "$ENV{ROOTDIR}/toolchain/iree/samples/models/mnist.mlir"
+  C_IDENTIFIER
+    "float_models_mnist"
+  FLAGS
+    "-iree-input-type=mhlo"
+    "-riscv-v-vector-bits-min=512"
+    "-riscv-v-fixed-length-vector-lmul-max=8"
+  RVV_OFF
+  PUBLIC
+)
+
+#-------------------------------------------------------------------------------
+# Binaries to execute the IREE model input
+#-------------------------------------------------------------------------------
+
+iree_model_input(
+  NAME
+    mobilenet_input
+  SHAPE
+    "1, 224, 224, 3"
+  SRC
+    "https://storage.googleapis.com/download.tensorflow.org/ \
+    example_images/YellowLabradorLooking_new.jpg"
+)
+
+iree_model_input(
+  NAME
+    mnist_input
+  SHAPE
+    "1, 28, 28, 1"
+  SRC
+    "https://github.com/google/iree/raw/ \
+    1e8d1fa96057c47d1fda918f3a2f71f14b073937/samples/iree_vision_inference/mnist_test.png"
+  RANGE
+    "0, 1"
+)
+
+#-------------------------------------------------------------------------------
+# Binaries to execute the MLIR bytecode modules
+#-------------------------------------------------------------------------------
+
+
+# If the program requires a larger stack size, add
+#
+#   LINKOPTS
+#     "LINKER:--defsym=__stack_size__=<new stack size>"
+#
+# to increase it.
+
+iree_cc_binary(
+  NAME
+    mobilenet_v1_bytecode_static
+  SRCS
+    "iree_exec/mobilenet_v1.c"
+  DEPS
+    ::mobilenet_v1_bytecode_module_static
+    ::mobilenet_v1_bytecode_module_static_c
+    ::mobilenet_input_c
+    samples::util::util
+    iree::vm::bytecode_module
+  LINKOPTS
+    "LINKER:--defsym=__stack_size__=200k"
+)
+
+springbok_test(
+  NAME
+    mobilenet_v1_emitc_static
+  SRCS
+    "iree_exec/mobilenet_v1.c"
+  DEPS
+    ::mobilenet_v1_c_module_static_c
+    ::mobilenet_v1_c_module_static_emitc
+    ::mobilenet_input_c
+    samples::util::util
+    "m"
+  LINKOPTS
+    "LINKER:--defsym=__stack_size__=200k"
+  COPTS
+    "-DBUILD_EMITC"
+  TESTFILES
+    "iree_exec/mobilenet_v1_test.run"
+    "iree_exec/mobilenet_v1_test.filecheck"
+)
+
+iree_cc_binary(
+  NAME
+    mnist_bytecode_static
+  SRCS
+    "iree_exec/mnist.c"
+  DEPS
+    ::mnist_bytecode_module_static
+    ::mnist_bytecode_module_static_c
+    ::mnist_input_c
+    iree::vm::bytecode_module
+    samples::util::util
+  LINKOPTS
+    "LINKER:--defsym=__stack_size__=100k"
+)
+
+springbok_test(
+  NAME
+    mnist_emitc_static
+  SRCS
+    "iree_exec/mnist.c"
+  DEPS
+    ::mnist_c_module_static_c
+    ::mnist_c_module_static_emitc
+    ::mnist_input_c
+    samples::util::util
+    "m"
+  LINKOPTS
+    "LINKER:--defsym=__stack_size__=100k"
+  COPTS
+    "-DBUILD_EMITC"
+  TESTFILES
+    "iree_exec/mnist_test.run"
+    "iree_exec/mnist_test.filecheck"
+)
diff --git a/float_models/iree_exec/mnist.c b/float_models/iree_exec/mnist.c
new file mode 100644
index 0000000..9fdcea6
--- /dev/null
+++ b/float_models/iree_exec/mnist.c
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2022 Google LLC
+ *
+ * Licensed 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.
+ */
+
+// mnist float model
+// MlModel struct initialization to include model I/O info.
+// Bytecode loading, input/output processes.
+
+#include "mnist.h"
+
+#include <springbok.h>
+
+#include "iree/base/api.h"
+#include "iree/hal/api.h"
+
+// Compiled module embedded here to avoid file IO:
+#if !defined(BUILD_EMITC)
+#include "mnist_bytecode_module_static.h"
+#include "mnist_bytecode_module_static_c.h"
+#else
+#include "mnist_c_module_static_c.h"
+#include "mnist_c_module_static_emitc.h"
+#endif
+#include "mnist_input_c.h"
+
+MnistOutput score;
+
+iree_status_t create_module(iree_vm_module_t **module) {
+#if !defined(BUILD_EMITC)
+  const struct iree_file_toc_t *module_file_toc =
+      float_models_mnist_bytecode_module_static_create();
+  return iree_vm_bytecode_module_create(
+      iree_make_const_byte_span(module_file_toc->data, module_file_toc->size),
+      iree_allocator_null(), iree_allocator_system(), module);
+#else
+  return module_create(iree_allocator_system(), module);
+#endif
+}
+
+iree_hal_executable_library_query_fn_t library_query(void) {
+  return &mnist_linked_llvm_library_query;
+}
+
+iree_status_t load_input_data(const MlModel *model, void **buffer,
+                              iree_const_byte_span_t **byte_span) {
+  byte_span[0] = malloc(sizeof(iree_const_byte_span_t));
+  *byte_span[0] = iree_make_const_byte_span(
+      mnist_input, model->input_size_bytes[0] * model->input_length[0]);
+  return iree_ok_status();
+}
+
+iree_status_t process_output(const MlModel *model,
+                             iree_hal_buffer_mapping_t *buffers,
+                             MlOutput *output) {
+  iree_status_t result = iree_ok_status();
+  // find the label index with best prediction
+  float best_out = 0.0;
+  int best_idx = -1;
+  for (int i = 0; i < model->output_length[0]; ++i) {
+    float out = ((float *)buffers[0].contents.data)[i];
+    if (out > best_out) {
+      best_out = out;
+      best_idx = i;
+    }
+  }
+
+  score.best_out = best_out;
+  score.best_idx = best_idx;
+
+  LOG_INFO("Digit recognition result is: digit: %d", best_idx);
+
+  output->result = &score;
+  output->len = sizeof(score);
+  return result;
+}
diff --git a/float_models/iree_exec/mnist.h b/float_models/iree_exec/mnist.h
new file mode 100644
index 0000000..2f866e5
--- /dev/null
+++ b/float_models/iree_exec/mnist.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2022 Google LLC
+ *
+ * Licensed 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.
+ */
+
+#ifndef FLOAT_MODELS_IREE_EXEC_MNIST_H_
+#define FLOAT_MODELS_IREE_EXEC_MNIST_H_
+
+#include <stdint.h>
+
+#include "samples/util/util.h"
+
+typedef struct {
+  int best_idx;
+  float best_out;
+} MnistOutput;
+
+const MlModel kModel = {
+    .num_input = 1,
+    .num_input_dim = {4},
+    .input_shape = {{1, 28, 28, 1}},
+    .input_length = {28 * 28 * 1},
+    .input_size_bytes = {sizeof(float)},
+    .num_output = 1,
+    .output_length = {10},
+    .output_size_bytes = sizeof(float),
+    .hal_element_type = IREE_HAL_ELEMENT_TYPE_FLOAT_32,
+    .entry_func = "module.predict",
+    .model_name = "mnist",
+};
+
+#endif  // FLOAT_MODELS_IREE_EXEC_MNIST_H_
diff --git a/float_models/iree_exec/mnist_test.filecheck b/float_models/iree_exec/mnist_test.filecheck
new file mode 100644
index 0000000..1e261ef
--- /dev/null
+++ b/float_models/iree_exec/mnist_test.filecheck
@@ -0,0 +1 @@
+// CHECK: digit: 4
diff --git a/float_models/iree_exec/mnist_test.run b/float_models/iree_exec/mnist_test.run
new file mode 100644
index 0000000..a7eb7cf
--- /dev/null
+++ b/float_models/iree_exec/mnist_test.run
@@ -0,0 +1,5 @@
+// RUN: ${TEST_RUNNER_CMD} %S/mnist_emitc_static 2>&1 | tee %t
+// RUN: cat %t | FileCheck %S/mnist_test.filecheck
+
+// RUN: ${TEST_RUNNER_CMD} %S/mnist_bytecode_static 2>&1 | tee %t
+// RUN: cat %t | FileCheck %S/mnist_test.filecheck
diff --git a/float_models/iree_exec/mobilenet_v1.c b/float_models/iree_exec/mobilenet_v1.c
new file mode 100644
index 0000000..d8cbadd
--- /dev/null
+++ b/float_models/iree_exec/mobilenet_v1.c
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2022 Google LLC
+ *
+ * Licensed 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.
+ */
+
+// Mobilenet_v1_0.25_224 float model
+// MlModel struct initialization to include model I/O info.
+// Bytecode loading, input/output processes.
+
+#include "mobilenet_v1.h"
+
+#include <springbok.h>
+
+#include "iree/base/api.h"
+#include "iree/hal/api.h"
+
+// Compiled module embedded here to avoid file IO:
+#include "mobilenet_input_c.h"
+#if !defined(BUILD_EMITC)
+#include "mobilenet_v1_bytecode_module_static.h"
+#include "mobilenet_v1_bytecode_module_static_c.h"
+#else
+#include "mobilenet_v1_c_module_static_c.h"
+#include "mobilenet_v1_c_module_static_emitc.h"
+#endif
+
+MobilenetV1Output score;
+
+iree_status_t create_module(iree_vm_module_t **module) {
+#if !defined(BUILD_EMITC)
+  const struct iree_file_toc_t *module_file_toc =
+      float_models_mobilenet_v1_bytecode_module_static_create();
+  return iree_vm_bytecode_module_create(
+      iree_make_const_byte_span(module_file_toc->data, module_file_toc->size),
+      iree_allocator_null(), iree_allocator_system(), module);
+#else
+  return module_create(iree_allocator_system(), module);
+#endif
+}
+
+iree_hal_executable_library_query_fn_t library_query(void) {
+#if !defined(BUILD_EMITC)
+  return &mobilenet_v1_bytecode_module_static_linked_llvm_library_query;
+#else
+  return &mobilenet_v1_c_module_static_linked_llvm_library_query;
+#endif
+}
+
+iree_status_t load_input_data(const MlModel *model, void **buffer,
+                              iree_const_byte_span_t **byte_span) {
+  byte_span[0] = malloc(sizeof(iree_const_byte_span_t));
+  *byte_span[0] = iree_make_const_byte_span(
+      mobilenet_input, model->input_size_bytes[0] * model->input_length[0]);
+  return iree_ok_status();
+}
+
+iree_status_t process_output(const MlModel *model,
+                             iree_hal_buffer_mapping_t *buffers,
+                             MlOutput *output) {
+  iree_status_t result = iree_ok_status();
+  // find the label index with best prediction
+  float best_out = 0.0;
+  int best_idx = -1;
+  for (int i = 0; i < model->output_length[0]; ++i) {
+    float out = ((float *)buffers[0].contents.data)[i];
+    if (out > best_out) {
+      best_out = out;
+      best_idx = i;
+    }
+  }
+  score.best_out = best_out;
+  score.best_idx = best_idx;
+
+  LOG_INFO("Image prediction result is: id: %d", best_idx + 1);
+
+  output->result = &score;
+  output->len = sizeof(score);
+  return result;
+}
diff --git a/float_models/iree_exec/mobilenet_v1.h b/float_models/iree_exec/mobilenet_v1.h
new file mode 100644
index 0000000..0196c6f
--- /dev/null
+++ b/float_models/iree_exec/mobilenet_v1.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2022 Google LLC
+ *
+ * Licensed 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.
+ */
+
+#ifndef FLOAT_MODELS_IREE_EXEC_MOBILENET_V1_H_
+#define FLOAT_MODELS_IREE_EXEC_MOBILENET_V1_H_
+
+#include <stdint.h>
+
+#include "samples/util/util.h"
+
+typedef struct {
+  int best_idx;
+  float best_out;
+} MobilenetV1Output;
+
+const MlModel kModel = {
+    .num_input = 1,
+    .num_input_dim = {4},
+    .input_shape = {{1, 224, 224, 3}},
+    .input_length = {224 * 224 * 3},
+    .input_size_bytes = {sizeof(float)},
+    .num_output = 1,
+    .output_length = {1001},
+    .output_size_bytes = sizeof(float),
+    .hal_element_type = IREE_HAL_ELEMENT_TYPE_FLOAT_32,
+    .entry_func = "module.main",
+    .model_name = "mobilenet_v1_0.25_224_float",
+};
+
+#endif  // FLOAT_MODELS_IREE_EXEC_MOBILENET_V1_H_
diff --git a/float_models/iree_exec/mobilenet_v1_test.filecheck b/float_models/iree_exec/mobilenet_v1_test.filecheck
new file mode 100644
index 0000000..847d8ca
--- /dev/null
+++ b/float_models/iree_exec/mobilenet_v1_test.filecheck
@@ -0,0 +1 @@
+// CHECK: Image prediction result is: id: 178
diff --git a/float_models/iree_exec/mobilenet_v1_test.run b/float_models/iree_exec/mobilenet_v1_test.run
new file mode 100644
index 0000000..aef0281
--- /dev/null
+++ b/float_models/iree_exec/mobilenet_v1_test.run
@@ -0,0 +1,5 @@
+// RUN: ${TEST_RUNNER_CMD} %S/mobilenet_v1_emitc_static 2>&1 | tee %t
+// RUN: cat %t | FileCheck %S/mobilenet_v1_test.filecheck
+
+// RUN: ${TEST_RUNNER_CMD} %S/mobilenet_v1_bytecode_static 2>&1 | tee %t
+// RUN: cat %t | FileCheck %S/mobilenet_v1_test.filecheck
diff --git a/quant_models/CMakeLists.txt b/quant_models/CMakeLists.txt
new file mode 100644
index 0000000..c9a9912
--- /dev/null
+++ b/quant_models/CMakeLists.txt
@@ -0,0 +1,191 @@
+# For the generated header files, include the generated directory path.
+# It is against the c-style recommendation, but we want to create a symlink of
+# this directory to ml/ml-models for the internal model zoo so all the models
+# can be built there.
+include_directories(BEFORE SYSTEM ${CMAKE_CURRENT_BINARY_DIR})
+
+# -------------------------------------------------------------------------------
+# Build the mlir bytecode modules with iree-compile. Note the last two flags
+# are for RVV support.
+# -------------------------------------------------------------------------------
+
+springbok_modules(
+  NAME
+  mobilenet_v1
+  SRC
+  "mobilenet_v1_0.25_224_quant.tflite"
+  C_IDENTIFIER
+  "quant_models_mobilenet_v1"
+  FLAGS
+  "-iree-input-type=tosa"
+  "-riscv-v-vector-bits-min=512"
+  "-riscv-v-fixed-length-vector-lmul-max=8"
+  PUBLIC
+)
+
+springbok_modules(
+  NAME
+    mobilenet_v2
+  SRC
+    "mobilenet_v2_1.0_224_quant.tflite"
+  C_IDENTIFIER
+    "quant_models_mobilenet_v2"
+  FLAGS
+    "-iree-input-type=tosa"
+    "-riscv-v-vector-bits-min=512"
+    "-riscv-v-fixed-length-vector-lmul-max=8"
+  PUBLIC
+)
+
+springbok_modules(
+  NAME
+  person_detection
+  SRC
+  "person_detection.tflite"
+  C_IDENTIFIER
+  "quant_models_person_detection"
+  FLAGS
+  "-iree-input-type=tosa"
+  "-riscv-v-vector-bits-min=512"
+  "-riscv-v-fixed-length-vector-lmul-max=8"
+  PUBLIC
+)
+
+# ------------------------------------------------------------------------------
+# Binaries to execute the IREE model input
+# ------------------------------------------------------------------------------
+
+iree_model_input(
+  NAME
+  mobilenet_quant_input
+  SHAPE
+  "1, 224, 224, 3"
+  SRC
+  "https://storage.googleapis.com/download.tensorflow.org/ \
+    example_images/YellowLabradorLooking_new.jpg"
+  QUANT
+)
+
+iree_model_input(
+  NAME
+  person_detection_quant_input
+  SHAPE
+  "1, 96, 96, 1"
+  SRC
+  "https://github.com/tensorflow/tflite-micro/raw/aeac6f39e5c7475cea20c54e86d41e3a38312546/ \
+    tensorflow/lite/micro/examples/person_detection/testdata/person.bmp"
+  QUANT
+)
+
+# ------------------------------------------------------------------------------
+# Binaries to execute the MLIR bytecode modules
+# ------------------------------------------------------------------------------
+
+# If the program requires a larger stack size, add
+#
+# LINKOPTS
+# "LINKER:--defsym=__stack_size__=<new stack size>"
+#
+# to increase it.
+
+iree_cc_binary(
+  NAME
+    mobilenet_v1_bytecode_static
+  SRCS
+    "iree_exec/mobilenet_v1.c"
+  DEPS
+    ::mobilenet_quant_input_c
+    ::mobilenet_v1_bytecode_module_static
+    ::mobilenet_v1_bytecode_module_static_c
+    iree::vm::bytecode_module
+    samples::util::util
+  LINKOPTS
+    "LINKER:--defsym=__stack_size__=300k"
+)
+
+springbok_test(
+  NAME
+    mobilenet_v1_emitc_static
+  SRCS
+    "iree_exec/mobilenet_v1.c"
+  DEPS
+    ::mobilenet_quant_input_c
+    ::mobilenet_v1_c_module_static_c
+    ::mobilenet_v1_c_module_static_emitc
+    samples::util::util
+  LINKOPTS
+    "LINKER:--defsym=__stack_size__=300k"
+  COPTS
+    "-DBUILD_EMITC"
+  TESTFILES
+    "iree_exec/mobilenet_v1_test.run"
+    "iree_exec/mobilenet_v1_test.filecheck"
+)
+
+iree_cc_binary(
+  NAME
+    mobilenet_v2_bytecode_static
+  SRCS
+    "iree_exec/mobilenet_v2.c"
+  DEPS
+    ::mobilenet_quant_input_c
+    ::mobilenet_v2_bytecode_module_static
+    ::mobilenet_v2_bytecode_module_static_c
+    iree::vm::bytecode_module
+    samples::util::util
+  LINKOPTS
+    "LINKER:--defsym=__stack_size__=300k"
+)
+
+springbok_test(
+  NAME
+    mobilenet_v2_emitc_static
+  SRCS
+    "iree_exec/mobilenet_v2.c"
+  DEPS
+    ::mobilenet_quant_input_c
+    ::mobilenet_v2_c_module_static_c
+    ::mobilenet_v2_c_module_static_emitc
+    samples::util::util
+  LINKOPTS
+    "LINKER:--defsym=__stack_size__=300k"
+  COPTS
+    "-DBUILD_EMITC"
+  TESTFILES
+    "iree_exec/mobilenet_v2_test.run"
+    "iree_exec/mobilenet_v2_test.filecheck"
+)
+
+iree_cc_binary(
+  NAME
+    person_detection_bytecode_static
+  SRCS
+    "iree_exec/person_detection.c"
+  DEPS
+    ::person_detection_bytecode_module_static
+    ::person_detection_bytecode_module_static_c
+    ::person_detection_quant_input_c
+    iree::vm::bytecode_module
+    samples::util::util
+  LINKOPTS
+    "LINKER:--defsym=__stack_size__=128k"
+)
+
+springbok_test(
+  NAME
+    person_detection_emitc_static
+  SRCS
+    "iree_exec/person_detection.c"
+  DEPS
+    ::person_detection_c_module_static_c
+    ::person_detection_c_module_static_emitc
+    ::person_detection_quant_input_c
+    samples::util::util
+  LINKOPTS
+    "LINKER:--defsym=__stack_size__=128k"
+  COPTS
+    "-DBUILD_EMITC"
+  TESTFILES
+    "iree_exec/person_detection_test.run"
+    "iree_exec/person_detection_test.filecheck"
+)
diff --git a/quant_models/iree_exec/mobilenet_v1.c b/quant_models/iree_exec/mobilenet_v1.c
new file mode 100644
index 0000000..641815e
--- /dev/null
+++ b/quant_models/iree_exec/mobilenet_v1.c
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2022 Google LLC
+ *
+ * Licensed 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.
+ */
+
+// Mobilenet_v1_0.25_224 quant model
+// MlModel struct initialization to include model I/O info.
+// Bytecode loading, input/output processes.
+
+#include "mobilenet_v1.h"
+
+#include <springbok.h>
+
+#include "iree/base/api.h"
+#include "iree/hal/api.h"
+
+// Compiled module embedded here to avoid file IO:
+#include "mobilenet_quant_input_c.h"
+#if !defined(BUILD_EMITC)
+#include "mobilenet_v1_bytecode_module_static.h"
+#include "mobilenet_v1_bytecode_module_static_c.h"
+#else
+#include "mobilenet_v1_c_module_static_c.h"
+#include "mobilenet_v1_c_module_static_emitc.h"
+#endif
+
+MobilenetV1Output score;
+
+iree_status_t create_module(iree_vm_module_t **module) {
+#if !defined(BUILD_EMITC)
+  const struct iree_file_toc_t *module_file_toc =
+      quant_models_mobilenet_v1_bytecode_module_static_create();
+  return iree_vm_bytecode_module_create(
+      iree_make_const_byte_span(module_file_toc->data, module_file_toc->size),
+      iree_allocator_null(), iree_allocator_system(), module);
+#else
+  return module_create(iree_allocator_system(), module);
+#endif
+}
+
+iree_hal_executable_library_query_fn_t library_query(void) {
+#if !defined(BUILD_EMITC)
+  return &mobilenet_v1_bytecode_module_static_linked_llvm_library_query;
+#else
+  return &mobilenet_v1_c_module_static_linked_llvm_library_query;
+#endif
+}
+
+iree_status_t load_input_data(const MlModel *model, void **buffer,
+                              iree_const_byte_span_t **byte_span) {
+  byte_span[0] = malloc(sizeof(iree_const_byte_span_t));
+  *byte_span[0] = iree_make_const_byte_span(
+      mobilenet_quant_input,
+      model->input_size_bytes[0] * model->input_length[0]);
+  return iree_ok_status();
+}
+
+iree_status_t process_output(const MlModel *model,
+                             iree_hal_buffer_mapping_t *buffers,
+                             MlOutput *output) {
+  iree_status_t result = iree_ok_status();
+  // find the label index with best prediction
+  int best_out = 0;
+  int best_idx = -1;
+  for (int i = 0; i < model->output_length[0]; ++i) {
+    uint8_t out = ((uint8_t *)buffers[0].contents.data)[i];
+    if (out > best_out) {
+      best_out = out;
+      best_idx = i;
+    }
+  }
+  score.best_out = best_out;
+  score.best_idx = best_idx;
+
+  LOG_INFO("Image prediction result is: id: %d", best_idx + 1);
+
+  output->result = &score;
+  output->len = sizeof(score);
+  return result;
+}
diff --git a/quant_models/iree_exec/mobilenet_v1.h b/quant_models/iree_exec/mobilenet_v1.h
new file mode 100644
index 0000000..c26a550
--- /dev/null
+++ b/quant_models/iree_exec/mobilenet_v1.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2022 Google LLC
+ *
+ * Licensed 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.
+ */
+
+#ifndef QUANT_MODELS_IREE_EXEC_MOBILENET_V1_H_
+#define QUANT_MODELS_IREE_EXEC_MOBILENET_V1_H_
+
+#include <stdint.h>
+
+#include "samples/util/util.h"
+
+typedef struct {
+  int best_idx;
+  int best_out;
+} MobilenetV1Output;
+
+const MlModel kModel = {
+    .num_input = 1,
+    .num_input_dim = {4},
+    .input_shape = {{1, 224, 224, 3}},
+    .input_length = {224 * 224 * 3},
+    .input_size_bytes = {sizeof(uint8_t)},
+    .num_output = 1,
+    .output_length = {1001},
+    .output_size_bytes = sizeof(uint8_t),
+    .hal_element_type = IREE_HAL_ELEMENT_TYPE_UINT_8,
+    .entry_func = "module.main",
+    .model_name = "mobilenet_v1_0.25_224_quant",
+};
+
+#endif  // QUANT_MODELS_IREE_EXEC_MOBILENET_V1_H_
diff --git a/quant_models/iree_exec/mobilenet_v1_test.filecheck b/quant_models/iree_exec/mobilenet_v1_test.filecheck
new file mode 100644
index 0000000..847d8ca
--- /dev/null
+++ b/quant_models/iree_exec/mobilenet_v1_test.filecheck
@@ -0,0 +1 @@
+// CHECK: Image prediction result is: id: 178
diff --git a/quant_models/iree_exec/mobilenet_v1_test.run b/quant_models/iree_exec/mobilenet_v1_test.run
new file mode 100644
index 0000000..aef0281
--- /dev/null
+++ b/quant_models/iree_exec/mobilenet_v1_test.run
@@ -0,0 +1,5 @@
+// RUN: ${TEST_RUNNER_CMD} %S/mobilenet_v1_emitc_static 2>&1 | tee %t
+// RUN: cat %t | FileCheck %S/mobilenet_v1_test.filecheck
+
+// RUN: ${TEST_RUNNER_CMD} %S/mobilenet_v1_bytecode_static 2>&1 | tee %t
+// RUN: cat %t | FileCheck %S/mobilenet_v1_test.filecheck
diff --git a/quant_models/iree_exec/mobilenet_v2.c b/quant_models/iree_exec/mobilenet_v2.c
new file mode 100644
index 0000000..2b00c89
--- /dev/null
+++ b/quant_models/iree_exec/mobilenet_v2.c
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2022 Google LLC
+ *
+ * Licensed 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.
+ */
+
+// Mobilenet_v2_1.0_224 quant model
+// MlModel struct initialization to include model I/O info.
+// Bytecode loading, input/output processes.
+
+#include "mobilenet_v2.h"
+
+#include <springbok.h>
+
+#include "iree/base/api.h"
+#include "iree/hal/api.h"
+
+// Compiled module embedded here to avoid file IO:
+#include "mobilenet_quant_input_c.h"
+#if !defined(BUILD_EMITC)
+#include "mobilenet_v2_bytecode_module_static.h"
+#include "mobilenet_v2_bytecode_module_static_c.h"
+#else
+#include "mobilenet_v2_c_module_static_c.h"
+#include "mobilenet_v2_c_module_static_emitc.h"
+#endif
+
+MobilenetV2Output score;
+
+iree_status_t create_module(iree_vm_module_t **module) {
+#if !defined(BUILD_EMITC)
+  const struct iree_file_toc_t *module_file_toc =
+      quant_models_mobilenet_v2_bytecode_module_static_create();
+  return iree_vm_bytecode_module_create(
+      iree_make_const_byte_span(module_file_toc->data, module_file_toc->size),
+      iree_allocator_null(), iree_allocator_system(), module);
+#else
+  return module_create(iree_allocator_system(), module);
+#endif
+}
+
+iree_hal_executable_library_query_fn_t library_query(void) {
+#if !defined(BUILD_EMITC)
+  return &mobilenet_v2_bytecode_module_static_linked_llvm_library_query;
+#else
+  return &mobilenet_v2_c_module_static_linked_llvm_library_query;
+#endif
+}
+
+iree_status_t load_input_data(const MlModel *model, void **buffer,
+                              iree_const_byte_span_t **byte_span) {
+  byte_span[0] = malloc(sizeof(iree_const_byte_span_t));
+  *byte_span[0] = iree_make_const_byte_span(
+      mobilenet_quant_input,
+      model->input_size_bytes[0] * model->input_length[0]);
+  return iree_ok_status();
+}
+
+iree_status_t process_output(const MlModel *model,
+                             iree_hal_buffer_mapping_t *buffers,
+                             MlOutput *output) {
+  iree_status_t result = iree_ok_status();
+  // find the label index with best prediction
+  int best_out = 0;
+  int best_idx = -1;
+  for (int i = 0; i < model->output_length[0]; ++i) {
+    uint8_t out = ((uint8_t *)buffers[0].contents.data)[i];
+    if (out > best_out) {
+      best_out = out;
+      best_idx = i;
+    }
+  }
+  score.best_out = best_out;
+  score.best_idx = best_idx;
+
+  LOG_INFO("Image prediction result is: id: %d", best_idx + 1);
+
+  output->result = &score;
+  output->len = sizeof(score);
+  return result;
+}
diff --git a/quant_models/iree_exec/mobilenet_v2.h b/quant_models/iree_exec/mobilenet_v2.h
new file mode 100644
index 0000000..049fe00
--- /dev/null
+++ b/quant_models/iree_exec/mobilenet_v2.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2022 Google LLC
+ *
+ * Licensed 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.
+ */
+
+#ifndef QUANT_MODELS_IREE_EXEC_MOBILENET_V2_H_
+#define QUANT_MODELS_IREE_EXEC_MOBILENET_V2_H_
+
+#include <stdint.h>
+
+#include "samples/util/util.h"
+
+typedef struct {
+  int best_idx;
+  int best_out;
+} MobilenetV2Output;
+
+const MlModel kModel = {
+    .num_input = 1,
+    .num_input_dim = {4},
+    .input_shape = {{1, 224, 224, 3}},
+    .input_length = {224 * 224 * 3},
+    .input_size_bytes = {sizeof(uint8_t)},
+    .num_output = 1,
+    .output_length = {1001},
+    .output_size_bytes = sizeof(uint8_t),
+    .hal_element_type = IREE_HAL_ELEMENT_TYPE_UINT_8,
+    .entry_func = "module.main",
+    .model_name = "mobilenet_v2_1.0_224_quant",
+};
+
+#endif  // QUANT_MODELS_IREE_EXEC_MOBILENET_V2_H_
diff --git a/quant_models/iree_exec/mobilenet_v2_test.filecheck b/quant_models/iree_exec/mobilenet_v2_test.filecheck
new file mode 100644
index 0000000..b225ec9
--- /dev/null
+++ b/quant_models/iree_exec/mobilenet_v2_test.filecheck
@@ -0,0 +1 @@
+// CHECK: Image prediction result is: id: 210
diff --git a/quant_models/iree_exec/mobilenet_v2_test.run b/quant_models/iree_exec/mobilenet_v2_test.run
new file mode 100644
index 0000000..1259a3d
--- /dev/null
+++ b/quant_models/iree_exec/mobilenet_v2_test.run
@@ -0,0 +1,5 @@
+// RUN: ${TEST_RUNNER_CMD} %S/mobilenet_v2_emitc_static 2>&1 | tee %t
+// RUN: cat %t | FileCheck %S/mobilenet_v2_test.filecheck
+
+// RUN: ${TEST_RUNNER_CMD} %S/mobilenet_v2_bytecode_static 2>&1 | tee %t
+// RUN: cat %t | FileCheck %S/mobilenet_v2_test.filecheck
diff --git a/quant_models/iree_exec/person_detection.c b/quant_models/iree_exec/person_detection.c
new file mode 100644
index 0000000..cc0b324
--- /dev/null
+++ b/quant_models/iree_exec/person_detection.c
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2022 Google LLC
+ *
+ * Licensed 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.
+ */
+
+// Person_detection quant model
+// MlModel struct initialization to include model I/O info.
+// Bytecode loading, input/output processes.
+
+#include "person_detection.h"
+
+#include <springbok.h>
+
+#include "iree/base/api.h"
+#include "iree/hal/api.h"
+
+// Compiled module embedded here to avoid file IO:
+#if !defined(BUILD_EMITC)
+#include "person_detection_bytecode_module_static.h"
+#include "person_detection_bytecode_module_static_c.h"
+#else
+#include "person_detection_c_module_static_c.h"
+#include "person_detection_c_module_static_emitc.h"
+#endif
+#include "person_detection_quant_input_c.h"
+
+PersonDetectionOutput detection;
+
+iree_status_t create_module(iree_vm_module_t **module) {
+#if !defined(BUILD_EMITC)
+  const struct iree_file_toc_t *module_file_toc =
+      quant_models_person_detection_bytecode_module_static_create();
+  return iree_vm_bytecode_module_create(
+      iree_make_const_byte_span(module_file_toc->data, module_file_toc->size),
+      iree_allocator_null(), iree_allocator_system(), module);
+#else
+  return module_create(iree_allocator_system(), module);
+#endif
+}
+
+iree_hal_executable_library_query_fn_t library_query(void) {
+#if !defined(BUILD_EMITC)
+  return &person_detection_bytecode_module_static_linked_llvm_library_query;
+#else
+  return &person_detection_c_module_static_linked_llvm_library_query;
+#endif
+}
+
+iree_status_t load_input_data(const MlModel *model, void **buffer,
+                              iree_const_byte_span_t **byte_span) {
+  byte_span[0] = malloc(sizeof(iree_const_byte_span_t));
+  *byte_span[0] = iree_make_const_byte_span(
+      person_detection_quant_input,
+      model->input_size_bytes[0] * model->input_length[0]);
+  return iree_ok_status();
+}
+
+iree_status_t process_output(const MlModel *model,
+                             iree_hal_buffer_mapping_t *buffers,
+                             MlOutput *output) {
+  iree_status_t result = iree_ok_status();
+  int8_t *data = (int8_t *)buffers[0].contents.data;
+  detection.non_person_score = data[0];
+  detection.person_score = data[1];
+
+  LOG_INFO("Output: Non-person Score: %d; Person Score: %d",
+           detection.non_person_score, detection.person_score);
+  output->result = &detection;
+  output->len = sizeof(detection);
+
+  return result;
+}
diff --git a/quant_models/iree_exec/person_detection.h b/quant_models/iree_exec/person_detection.h
new file mode 100644
index 0000000..d089e50
--- /dev/null
+++ b/quant_models/iree_exec/person_detection.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2022 Google LLC
+ *
+ * Licensed 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.
+ */
+
+#ifndef QUANT_MODELS_IREE_EXEC_PERSON_DETECTION_H_
+#define QUANT_MODELS_IREE_EXEC_PERSON_DETECTION_H_
+
+#include <stdint.h>
+
+#include "samples/util/util.h"
+
+typedef struct {
+  int8_t non_person_score;
+  int8_t person_score;
+} PersonDetectionOutput;
+
+const MlModel kModel = {
+    .num_input = 1,
+    .num_input_dim = {4},
+    .input_shape = {{1, 96, 96, 1}},
+    .input_length = {96 * 96 * 1},
+    .input_size_bytes = {sizeof(int8_t)},
+    .num_output = 1,
+    .output_length = {2},
+    .output_size_bytes = sizeof(int8_t),
+    .hal_element_type = IREE_HAL_ELEMENT_TYPE_SINT_8,
+    .entry_func = "module.main",
+    .model_name = "person_detection_quant",
+};
+
+#endif  // QUANT_MODELS_IREE_EXEC_PERSON_DETECTION_H_
diff --git a/quant_models/iree_exec/person_detection_test.filecheck b/quant_models/iree_exec/person_detection_test.filecheck
new file mode 100644
index 0000000..c84bff9
--- /dev/null
+++ b/quant_models/iree_exec/person_detection_test.filecheck
@@ -0,0 +1 @@
+// CHECK: Non-person Score: -113; Person Score: 113
diff --git a/quant_models/iree_exec/person_detection_test.run b/quant_models/iree_exec/person_detection_test.run
new file mode 100644
index 0000000..7c95b7b
--- /dev/null
+++ b/quant_models/iree_exec/person_detection_test.run
@@ -0,0 +1,5 @@
+// RUN: ${TEST_RUNNER_CMD} %S/person_detection_emitc_static 2>&1 | tee %t
+// RUN: cat %t | FileCheck %S/person_detection_test.filecheck
+
+// RUN: ${TEST_RUNNER_CMD} %S/person_detection_bytecode_static 2>&1 | tee %t
+// RUN: cat %t | FileCheck %S/person_detection_test.filecheck