AN 1011: TinyML Applications in Altera FPGAs Using LiteRT for Microcontrollers

ID 848984
Date 4/07/2025
Public

Visible to Intel only — GUID: aru1740462455501

Ixiasoft

Document Table of Contents

6.1. main.cc for Nios V Processor

#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <math.h>
#include "system.h"
#include <time.h>
#include <unistd.h>

//Import TensorFlow lite libraries
#include "tensorflow/lite/core/c/common.h"
#include "tensorflow/lite/micro/micro_interpreter.h"
#include "tensorflow/lite/micro/micro_log.h"
#include "tensorflow/lite/micro/micro_time.h"
#include "tensorflow/lite/micro/micro_mutable_op_resolver.h"
#include "tensorflow/lite/micro/micro_profiler.h"
#include "tensorflow/lite/micro/recording_micro_interpreter.h"
#include "tensorflow/lite/micro/system_setup.h"
#include "tensorflow/lite/schema/schema_generated.h"

//Model data
#include "model/model_data.h"
#include "model/model_settings.h"

////Sample image
#include "image/figure-0.h"
#include "image/figure-1.h"
#include "image/figure-2.h"
#include "image/figure-3.h"
#include "image/figure-4.h"
#include "image/figure-5.h"
#include "image/figure-6.h"
#include "image/figure-7.h"
#include "image/figure-8.h"
#include "image/figure-9.h"

#define IMAGE_WIDTH 28
#define IMAGE_HEIGHT 28
#define NUM_CHANNELS 1
#define IMAGE_SIZE (IMAGE_WIDTH * IMAGE_HEIGHT * NUM_CHANNELS)

//ANSI Escape code
#define CRESET "\033[m"

int count;
uint8_t test_image[IMAGE_HEIGHT][IMAGE_WIDTH][NUM_CHANNELS];
 

namespace {
	const tflite::Model* model = nullptr;

	using OpResolver = tflite::MicroMutableOpResolver<5>;
	TfLiteStatus RegisterOps(OpResolver& op_resolver) {
		TF_LITE_ENSURE_STATUS(op_resolver.AddConv2D());
		TF_LITE_ENSURE_STATUS(op_resolver.AddAveragePool2D());
		TF_LITE_ENSURE_STATUS(op_resolver.AddReshape());
		TF_LITE_ENSURE_STATUS(op_resolver.AddFullyConnected());
		TF_LITE_ENSURE_STATUS(op_resolver.AddSoftmax());
		return kTfLiteOk;
	}
}  // namespace

TfLiteStatus LoadModelandInference() {

	printf("[INFO]Setting up TinyML...\n\r");
	tflite::MicroProfiler profiler;
	OpResolver op_resolver;
	TF_LITE_ENSURE_STATUS(RegisterOps(op_resolver));
	model = tflite::GetModel(lenet_tflite);
	TFLITE_CHECK_EQ(model->version(), TFLITE_SCHEMA_VERSION);

	/* Arena size is a round number, which is determined
	 * using the RecordingMicroInterpreter.
	 */
	constexpr int kTensorArenaSize = 20000;
	uint8_t tensor_arena[kTensorArenaSize];
	constexpr int kNumResourceVariables = 24;

	tflite::RecordingMicroAllocator* allocator(
	  tflite::RecordingMicroAllocator::Create(tensor_arena, kTensorArenaSize));
	tflite::RecordingMicroInterpreter Recordinginterpreter(
	  model, op_resolver, allocator,
	  tflite::MicroResourceVariables::Create(allocator, kNumResourceVariables),
	  &profiler);

	TF_LITE_ENSURE_STATUS(Recordinginterpreter.AllocateTensors());
	TFLITE_CHECK_EQ(Recordinginterpreter.inputs_size(), 1);

	//Print loaded model input and output shape
	printf("Total output layers: %d\n\r", Recordinginterpreter.outputs_size());	printf("Input shape: %d dimensions. Dimension: %d %d %d %d. Type: %d\n\r",
      Recordinginterpreter.input(0)->dims->size,	
      Recordinginterpreter.input(0)->dims->data[0],
      Recordinginterpreter.input(0)->dims->data[1],
      Recordinginterpreter.input(0)->dims->data[2],
      Recordinginterpreter.input(0)->dims->data[3],
      Recordinginterpreter.input(0)->type
	);

	for (int i = 0; i < (int)(Recordinginterpreter.outputs_size()); ++i)
	  printf( "Output shape %d: %d dimensions. Dimension: %d %d. Type: %d\n\r",
		i, 
		Recordinginterpreter.output(i)->dims->size,
		Recordinginterpreter.output(i)->dims->data[0],
		Recordinginterpreter.output(i)->dims->data[1],
		Recordinginterpreter.output(i)->type
	  );

	printf("[INFO]Setting up TinyML...Done\n\n\r");

	printf("[INFO]Uploading image...\n\r");

	//Visualize sample image in terminal
	int HashTag = 35;
	for (int i = 0; i < IMAGE_HEIGHT; i=i+2){
		for (int j = 0; j < IMAGE_WIDTH; j=j+2){
			printf("\033[38;2;%d;%d;%dm%c"
					CRESET,
					test_image[i][j][0],
					test_image[i][j][0],
					test_image[i][j][0],
					HashTag);
		}
		printf("\n");
	}
	printf("\n");

	//Input sample image to tflite model input.
	int len = 0;
	for (int i = 0; i < IMAGE_HEIGHT; i++){
		for (int j = 0; j < IMAGE_WIDTH; j++){
			for (int k = 0; k < NUM_CHANNELS; k++){
				Recordinginterpreter.input(0)->data.f[len] = 
				float(test_image[i][j][k])/255.0;
				len++;
			}
		}
	}
	printf("[INFO]Uploading image...Done\n\n\r");



	printf("[INFO]Classifying image...\n\r");
	clock_t startTime = clock();
	TF_LITE_ENSURE_STATUS(Recordinginterpreter.Invoke());
	clock_t endTime = clock();
	printf("[INFO]Classifying image...Done\n\n\r");

	//Retrieve inference output
	int answer = 0;
	printf("Retrieve the inference output:\n");
	for (int i = 0; i < kCategoryCount; ++i){
	  printf("%s score: %f\n\r", 
			kCategoryLabels[i], 
			Recordinginterpreter.output(0)->data.f[i]);
	  if (Recordinginterpreter.output(0)->data.f[i] > 
			Recordinginterpreter.output(0)->data.f[answer]) answer = i;
	  }
	printf("\nInference made: %s\n\r", kCategoryLabels[answer]);
	int time_spent = int(endTime - startTime) / ALT_CPU_TICKS_PER_SEC;
	printf("Inference time: %d seconds\n\n\r", time_spent);
 

	printf("[INFO]Profiling TinyML model...\n\r");
	profiler.LogTicksPerTagCsv();
	printf("Ticks per seconds: %d\n\n", ALT_CPU_TICKS_PER_SEC);

	printf("Tensor Arena Allocation:\n");
	Recordinginterpreter.GetMicroAllocator().PrintAllocations();
	printf("[INFO]Profiling TinyML model...Done\n\n\r");

  return kTfLiteOk;
}

int SelectImage(uint8_t (*image)[IMAGE_WIDTH][NUM_CHANNELS]){
	for (int i = 0; i < IMAGE_HEIGHT; i++){
	   	for (int j = 0; j < IMAGE_WIDTH; j++){
	   		for (int k = 0; k < NUM_CHANNELS; k++){
	   			test_image[i][j][k] = image[i][j][k];
	   		}
	   	}
	}
	TF_LITE_ENSURE_STATUS(LoadModelandInference());

	return 0;
}


int main() {

   printf("\tHello from Nios V Processor TinyML Demonstration on MNIST\n\r");
   /*************************TFLITE-MICRO TINYML******************/

   SelectImage(test_image0);
   SelectImage(test_image1);
   SelectImage(test_image2);
   SelectImage(test_image3);
   SelectImage(test_image4);
   SelectImage(test_image5);
   SelectImage(test_image6);
   SelectImage(test_image7);
   SelectImage(test_image8);
   SelectImage(test_image9);

   return 0;
}