|
|
|
|
|
### Overview
|
|
|
|
|
|
The TFMin library generates C++11 compliant code which can be compiled on a wide range of systems,
|
|
|
however it was originally developed to deploy TensorFlow models onto the LEON 3 family of
|
|
|
radiation hardened processors developed by the European Space Agency. These processors are based on the
|
|
|
open-source Sparc-V8 CPU architecture developed by Sun Microsystems with several levels of radiation
|
|
|
hardening and a range of space-specific peripheral hardware options.
|
|
|
|
|
|
The following sections describe the additional open source tools
|
|
|
that need to be installed and setup in order to build TFMin generated code into LEON 3 compatible binaries.
|
|
|
|
|
|
##### Step 1 - Install a LEON 3 Compiler
|
|
|
Download the BCC 2 compiler collection from Cobham Gaisler [download](https://www.gaisler.com/index.php/downloads/compilers)
|
|
|
|
|
|
Two LEON build tool-chains are provided in this package; a GCC based compiler and an LLVM based compiler, both have some
|
|
|
support for the C++ 11 standard. Both of these compilers have been tested and are compatible with the code
|
|
|
generated by this library.
|
|
|
|
|
|
You will need to add the binary location to the GCC LEON compiler to your path for the examples presented here
|
|
|
to work, we recommend you also add the path to the LLVM compiler, CLANG, too.
|
|
|
|
|
|
##### Step 2 - Install a LEON 3 Emulator
|
|
|
|
|
|
Download the free evaluation version of TSim 2 from Cobham Gaisler [download](https://www.gaisler.com/index.php/downloads/simulators).
|
|
|
Cobham Gaisler provide a free restricted version of their LEON emulator, its runtime and RAM is fairly
|
|
|
limited but it is able to execute the two MNIST examples provided with TFMin. The larger SqueezeNet example
|
|
|
needs either the commercial version of TSim or actual LEON 3 hardware to run.
|
|
|
|
|
|
|
|
|
##### Step 3 - Install a LEON 3 Compatible version of the Eigen Library
|
|
|
* Clone from this [repository here](https://github.com/PeteBlackerThe3rd/eigen-git-mirror)
|
|
|
|
|
|
The Eigen library requires some minor patching to compile successfully using the LEON 3 compilers,
|
|
|
this patched version can be downloaded from the repository shown above. This repository contains
|
|
|
many things, but we're not interested in the tests, benchmarks, etc, only the header library itself.
|
|
|
You'll need to copy the `Eigen` and `unsupported` folders into the include folder for the LEON
|
|
|
compiler your using, this will be one or both of the following depending which compilers you have
|
|
|
installed:
|
|
|
* bcc-2.x.x-gcc/sparc-gaisler-elf/include
|
|
|
* bcc-2.x.x.llvm/sparc-gaisler-elf/include
|
|
|
|
|
|
##### Step 4 - Test LEON 3 Build Chain
|
|
|
|
|
|
If we use the MNIST dense example model and perform a clean build using the provided Makefile it
|
|
|
should detect the new compiler and cross-compile the LEON version automatically!
|
|
|
|
|
|
```bash
|
|
|
$ make clean
|
|
|
$ make
|
|
|
Building implementation of mnist model
|
|
|
Build succeeded.
|
|
|
Building LEON implementation of mnist model
|
|
|
LEON build succeeded.
|
|
|
$
|
|
|
|
|
|
```
|
|
|
|
|
|
If the leon binary has been created you will now be able to execute it using the TSim emulator as
|
|
|
shown below:
|
|
|
|
|
|
```
|
|
|
$ tsim-leon3 leon_test
|
|
|
|
|
|
This TSIM evaluation version will expire 2019-05-13
|
|
|
|
|
|
|
|
|
TSIM/LEON3 SPARC simulator, version 2.0.62 (evaluation version)
|
|
|
|
|
|
Copyright (C) 2018, Cobham Gaisler - all rights reserved.
|
|
|
This software may only be used with a valid license.
|
|
|
For latest updates, go to http://www.gaisler.com/
|
|
|
Comments or bug-reports to support@gaisler.com
|
|
|
|
|
|
system frequency: 50.000 MHz
|
|
|
serial port A on stdin/stdout
|
|
|
allocated 4096 KiB SRAM memory, in 1 bank
|
|
|
allocated 32 MiB SDRAM memory, in 1 bank
|
|
|
allocated 2048 KiB ROM memory
|
|
|
icache: 1 * 4 KiB, 16 bytes/line (4 KiB total)
|
|
|
dcache: 1 * 4 KiB, 16 bytes/line (4 KiB total)
|
|
|
file "load" not found
|
|
|
section: .text, addr: 0x40000000, size 871856 bytes
|
|
|
section: .gcc_except_table, addr: 0x400d4db0, size 392 bytes
|
|
|
section: .rodata, addr: 0x400d4f38, size 35624 bytes
|
|
|
section: .gcc_except_table._ZNSt6vectorIN5TFMin13OperationTimeESaIS1_EEC2ERKS3_, addr: 0x400dda60, size 44 bytes
|
|
|
section: .gcc_except_table.__gxx_personality_v0, addr: 0x400dda8c, size 28 bytes
|
|
|
section: .gcc_except_table.__cxa_call_unexpected, addr: 0x400ddaa8, size 32 bytes
|
|
|
:
|
|
|
:
|
|
|
:
|
|
|
section: .gcc_except_table._ZNSi6ignoreEi, addr: 0x400e2508, size 64 bytes
|
|
|
section: .gcc_except_table._ZNSt13basic_istreamIwSt11char_traitsIwEE6ignoreEi, addr: 0x400e2548, size 64 bytes
|
|
|
section: .gcc_except_table._ZnwjRKSt9nothrow_t, addr: 0x400e2588, size 20 bytes
|
|
|
section: .data, addr: 0x400e25a0, size 963832 bytes
|
|
|
read 6177 symbols
|
|
|
tsim> run
|
|
|
starting at 0x40000000
|
|
|
Running model plain.
|
|
|
Done.
|
|
|
about to verify terrain model.
|
|
|
Validating model computations against stored results from TensorFlow
|
|
|
Eigen Version 3.3.90
|
|
|
About to perform MatMul operation [layer1/Wx_plus_b/$ MatMul]
|
|
|
Passed
|
|
|
About to perform Add operation [layer1/Wx_plus_b/add]
|
|
|
Passed
|
|
|
About to perform Mul operation [layer1/activation/mul]
|
|
|
Passed
|
|
|
About to perform Maximum operation [layer1/activation/Maximum]
|
|
|
Passed
|
|
|
About to perform MatMul operation [layer2/Wx_plus_b/MatMul]
|
|
|
Passed
|
|
|
About to perform Add operation [layer2/Wx_plus_b/add]
|
|
|
Passed
|
|
|
Verification Passed.
|
|
|
get time performance of model.
|
|
|
Operating timing results for
|
|
|
0.09818 seconds, layer1/Wx_plus_b/MatMul
|
|
|
0.000151992 seconds, layer1/Wx_plus_b/add
|
|
|
0.000117987 seconds, layer1/activation/mul
|
|
|
0.000140011 seconds, layer1/activation/Maximum
|
|
|
0.001322 seconds, layer2/Wx_plus_b/MatMul
|
|
|
9.0003e-06 seconds, layer2/Wx_plus_b/add
|
|
|
0.099921, Total duration
|
|
|
Completed running terrain model.
|
|
|
|
|
|
Program exited normally.
|
|
|
tsim> quit
|
|
|
$
|
|
|
```
|
|
|
|
|
|
Congratulations you have now successfully exported a TensorFlow model to C++, then build and
|
|
|
executed it for the LEON 3 processor. It is interesting to note the speed difference between the LEON 3
|
|
|
code and the native test (executed on an Intel i7), The LEON 3 is approximately a thousand times slower.
|
|
|
This is the price we have to pay when working on computers that can withstand over 100 KRads of radiation!
|
|
|
|
|
|
##### The Cross Compilation Makefile
|
|
|
|
|
|
```Makefile
|
|
|
# TFMin MNIST dense example project makefile
|
|
|
|
|
|
native_compiler = g++
|
|
|
cross_compiler = sparc-gaisler-elf-g++
|
|
|
generated_code_path = ../tfmin_generated/
|
|
|
|
|
|
cpp_flags = -std=c++11 -O3
|
|
|
native_flags = -pthread -DEIGEN_USE_THREADS
|
|
|
cross_compiler_flags = -DLEON
|
|
|
|
|
|
ifneq (, $(shell which $(cross_compiler)))
|
|
|
all : native_test leon_test
|
|
|
else
|
|
|
all : native_test
|
|
|
endif
|
|
|
|
|
|
# build native binary
|
|
|
native_test : test_mnist.cpp $(generated_code_path)mnist_model.cpp
|
|
|
$(info Building implementation of mnist model)
|
|
|
@(g++ $(cpp_flags) $(native_flags) -o native_test test_mnist.cpp $(generated_code_path)mnist_model.cpp -I $(generated_code_path)) && echo "Build succeeded."
|
|
|
|
|
|
# build leon 3 binary
|
|
|
leon_test : test_mnist.cpp $(generated_code_path)mnist_model.cpp
|
|
|
$(info Building LEON implementation of mnist model)
|
|
|
@(sparc-gaisler-elf-g++ $(cpp_flags) $(cross_compiler_flags) -o leon_test test_mnist.cpp $(generated_code_path)mnist_model.cpp -I $(generated_code_path)) && echo "LEON build succeeded."
|
|
|
|
|
|
clean :
|
|
|
$(info cleaning build files)
|
|
|
@rm -f leon_test native_test
|
|
|
```
|
|
|
|
|
|
Lets break down the makefile used to build the native and cross compiled versions of this project. First
|
|
|
the two compilers to use are defined along with the relative path to the source files generated by the
|
|
|
python script. Here you can switch to the LLVM compiler if it is more suitable to your project.
|
|
|
|
|
|
Next the flags for both compilers and any platform specific flags are defined. Then we use a shell
|
|
|
command to detect the presence of the GCC based LEON compiler and add an additional target if it exists.
|
|
|
|
|
|
The makefile then continues defining the two build targets.
|
|
|
|
|
|
### Summary
|
|
|
You have now successfully deployed a simple TensorFlow neural network onto the LEON 3 processor. If you've
|
|
|
got this far you are probably part of a very small group of people who is working in the overlap between
|
|
|
deep learning and spacecraft on-board data processing. If so please follow my published research in the same area
|
|
|
and I hope we can work together.
|
|
|
|
|
|
[Pete Blacker - Google Scholar](https://scholar.google.com/)
|
|
|
|
|
|
---
|
|
|
[Previous Tutorial](/Tutorials/Tutorial-4-Adding-Support-for-More-Operations) - Adding Support for More Operations |