Files needed to deploy neural networks on Zynq-Z7 with TF lite micro together instructions how to do it and with python script to convert TF models directly to the C++ files which TF micro can use.
TFmicroZynqSrc/
- Files which needs to be included as part of your Zynq C++ firmware projectAuxiliary_Files/
- Files which were altered, removed or added related to default to make the deployment possibleTFmicroZynqLib/
- TF micro library compiled as static library.TFmicroZynqLib/libTFmicroZynq.a
- The static library archive fileTFmicroZynqLib/TFmicroZynqHeaders/
- Include the headers file for the library. At the moment of writing this README, it is exact copy ofTFmicroZynqSrc/
just with .cc files removed.TFmicroZynqLib/tfmicrozynq.h
- header-only interface layer for the library to simplify including tf micro library. Just include this file in your project.
Convert_Network_To_TFlitemicro.py
- Launch this script to convert your neural network to TFmicro format.Example/
- Example of how to use the TFmicro on Zynq-Z7 You can also find relevant parameters in this script.
I've tested 2 ways of including TF micro in Vitis project:
- Including files in the project and building everything together. First build takes a lot of time, but later incremental builds are fast. It is however to me difficult to predict when Vitis decides it needs to rebuild everything.
- Building TF micro as a static library and linking it to the project. Slow build of the library, but builds of the application are very fast.
We first describe how to compile TF micro file together with your application, below instructions how to compile and use TF micro as static library.
-
Create a new application project, We tested it with the "Empty Application (C++)" template.
-
Copy the
TFmicroZynqSrc/
directory to thesrc/
directory of your project, or create a symbolic link. Don't use Vitis to create the symbolic link, as the compilation fail for us if we do so. Instead use the tools of your OS. E.g. on Ubuntu you can open TFmicroZynq and your Vitis project in two windows of file system, and drag theTFmicroZynqSrc/
directory to thesrc/
directory of your project while holding shift and ctrl keys. -
Right click on the {project_name}_system in Explorer pane, select "C/C++ Build Settings". You might want to change "Configuration:" to "All configurations", as the changes are needed in both release and debug configuration if you want to use them. In Settings -> Tool Settings -> System Builder -> Miscellaneous -> Other flags add:
-std=c++2a
and click "Apply and Close". This will allow you to use C++20 features on the system level. You can also activate the "Verbose" checkbox (optional). -
Right click on the {project_name} in Explorer pane (one line below where you were before), select "C/C++ Build Settings", go to Settings. You might want to again change "Configuration:" to "All configurations".
- Assembler (ARM v7 gcc assembler) -> General -> Include paths (-I) -> add (icon with plus) -> Workspace... ->
select the
TFmicroZynqSrc/
,flatbuffers/include
,gemmlowp
,kissfft
ruy
click "OK" and "Apply". Notice that you need to select include folder inside flatbuffers, not the flatbuffers folder itself. See the screenshot below, how it should look like. The paths in the "Include Paths (-I)" window will appear only after clicking "OK". - Compiler (ARM v7 g++ compiler) -> Directories -> Include paths, Add the same paths as in the previous step, click "Apply".
- Compiler (ARM v7 g++ compiler) -> Defined Symbols -> Defined symbols (-D), add:
TF_LITE_STATIC_MEMORY
, click "Apply". It seems without this flag TF micro tries to compile in some obsolete, no longer supported & no compilable mode. - Compiler (ARM v7 g++ compiler) -> Miscellaneous -> Other flags, add:
-std=c++2a -fno-exceptions
, click "Apply". First flag allows you to use C++20 features in the code, second flag disables exceptions, which leads to crash of the compilation, without being essential for the TFmicro. - Linker -> Libraries -> Libraries (-l), add:
m
, click "Apply". This will link the standard math library. - Optional: Compiler (ARM v7 g++ compiler) -> Optimization -> Optimization Level, for Debug configuration set to "None (-O0)", for Release configuration set to "Optimize most (-O3)".
- Assembler (ARM v7 gcc assembler) -> General -> Include paths (-I) -> add (icon with plus) -> Workspace... ->
select the
-
Click on the {project_name}_system in Explorer pane, either right click and select Build Project or click on the hammer icon. Clicking at a small arrow next to the hammer icon, you can select build configuration.
-
Do points 1-3 from the previous section (A.). Just instead of copying the
TFmicroZynqSrc/
directory, copy theTFmicroZynqLib/
directory to thesrc/
directory of your project. -
Right-click on the {project_name} in Explorer pane (one line below where you were before), select "C/C++ Build Settings", go to Settings. You might want to change "Configuration:" to "All configurations".
- Compiler (ARM v7 g++ compiler) -> Directories -> Include paths -> add (icon with plus) -> Workspace... ->
select the
TFmicroLib/TFmicroZynqHeaders/
,flatbuffers/include
,gemmlowp
,kissfft
ruy
click "OK" and "Apply". Notice that you need to select include folder inside flatbuffers, not the flatbuffers folder itself. See the screenshot for section A.4., how it should look like. Notice that in contrast to A.4. here the parent directory isTFmicroZynqLib/
notTFmicroZynqSrc/
. The paths in the "Include Paths (-I)" window will appear only after clicking "OK". Click "Apply". - Compiler (ARM v7 g++ compiler) -> Miscellaneous -> Other flags, add:
-std=c++2a
, click "Apply". - Linker -> Libraries:
- -> Libraries (-l) -> add
m
, click "OK". This will link the standard math library. - -> Libraries (-l) -> add
TFmicroZynq
، click "OK" (This should be the name of .a library file without thelib
prefix and.a
suffix). - Library search path -> add (icon with plus) -> Workspace... -> select the
TFmicroZynqLib/
directory, click "OK" and "Apply".
- -> Libraries (-l) -> add
- Optional: Compiler (ARM v7 g++ compiler) -> Optimization -> Optimization Level, for Debug configuration set to "None (-O0)", for Release configuration set to "Optimize most (-O3)".
- Compiler (ARM v7 g++ compiler) -> Directories -> Include paths -> add (icon with plus) -> Workspace... ->
select the
-
Click on the {project_name}_system in Explorer pane, either right click and select Build Project or click on the hammer icon. Clicking at a small arrow next to the hammer icon, you can select build configuration.
-
Create a new library project. Name it
TFmicroZynq
. You can also name it differently, but then your static library archive file (a.) will have a different name than in section B. You need to select a hardware platform, but as this library does not communicate to PL, it seems to work properly also if you later use the compiled library with an application using different hardware platform. Use Empty Application (C++) template. -
Follow the steps A.2., A.3, A.4. You will need to skip the linking math library step. I built it only in release configuration. I set the optimization level to "Optimize most (-O3)" and Debug None to increase the performance. You can use the library with higher level of optimization and no debugging, with an application with different settings.
-
Click on the {project_name} in Explorer pane, either right click and select Build Project or click on the hammer icon. Clicking at a small arrow next to the hammer icon, you can select build configuration.
-
After the build is finished, you can find the static library
libTFmicroZynq.a
archive file in theDebug/
orRelease/
directory of your project. If you click on {project_name}_system and request the build the Vitis will claim that the build failed, as it will try to obtain a bootable image. If the settings for library compilation were correct, the library should be however still compiled correctly and the .a file should be available.
Just copy the files from the Example/
directory of this repo to the src/
directory of your project and build the project.
This example is based on the default hellow_world example for TF micro, but for a multi input network with tanh activation.
The script Convert_Network_To_TFliteMicoro.py
was intended to work with networks created with SI_Toolkit,
and hence make use of additional metadata ("net_info").
It would be however easily adjustable to convert any networks to TFmicro format:
just replace the import of the network model, with your function and provide the size of the input tensor.
You can provide the path to your network in Convert_Network_To_TFliteMicoro.py
,
the newly generated files will be saved in the same location.
You can directly use it with the example above,
just copy the generated files to the src/
directory of your project,
and change the #include "Dense_7IN_32H1_32H2_1OUT_0_model.h"
header in the hello_world_test.cc
appropriately.
Additionally, the python script generated the golden input and output for the network,
which you should exchange in the hello_world_test.cc
file for network to pass the tests.
We followed step 1 from the official
instruction,
for creating tensorflow micro files from general repository.
We removed the example folder, tensorflow/lite/micro/span_test.cc
and tensorflow/lite/micro/static_vector_test.cc
,
and modified tensorflow/lite/micro/micro_time.cc
and tensorflow/lite/micro/system_setup.cc
These are files which needed to be removed from the default files package to make compilation possible.
tensorflow/lite/micro/span_test.cc
and tensorflow/lite/micro/static_vector_test.cc
comes with their own main function.
One can just exclude them from the compilation,
but to make setup easier we removed them from sources to be imported into the project.
If you happen to need them and rather exclude them from compilation, just right-click on the file in the Explorer pane, select "Properties" -> "C/C++ Build" -> "Exclude resource from build". The option is available only if you click on a single file, not multiple files at once. You can also select to exclude with form one or all configurations.
We also removed from TFmicroZynqSrc the whole official examples
folder,
which can be found now in Auxiliary_Files/Removed
.
As described in the instruction for creating tensorflow micro files from general repository, one need in general to adjust these files:
tensorflow/lite/micro/debug_log.cc
tensorflow/lite/micro/micro_time.cc
tensorflow/lite/micro/system_setup.cc
For Zynq Z7 debug_log.cc
the default implementation works fine.
Following the Sparkfun Edge example,
mentioned in the above-mentioned instruction,
We cleared all content from micro_time.cc
and put initialization and timing functions into system_setup.cc
.
The modified files are at the location named above and the original files are in the Auxiliary_Files/Altered
directory.
The program compiles quite long! Probably around 10 minutes for the first time. Later incremental compilation is completed usually within few seconds.
TF lite takes roughly 0.5 MB of memory.
The network built in Release configuration is roughly 3x faster than network built in Debug configuration.
We purposely did not include this repo as submodule of the Neural Control Tools as it is quite big and needed only for few experiments.
The Zynq Z7 PS (ARM Cortex A9) has a VFPv3 floating point unit.
It usage is enabled by default in the compiler with the flags -mfpu=vfpv3 -mfloat-abi=hard
.
It should handle single and double precision floating point operations.
Wikipedia states
that disabling it should "require roughly ten times more clock cycles per float operation." TODO: check this.
It should be also possible to enable the NEON unit with the flags
-mfpu=neon -funsafe-math-optimizations -mfloat-abi=hard
but when we tested we got a slight increase of computation time (from 45 us to 48 us).
Maybe it needs some more changes to enable correctly? We don't know.
We see there are similar flags for linker, not only compiler, maybe this is the reason?