Exporting a Library for GCC
This chapter demonstrates how to use the sds++
compiler to build a library of software functions with entry points into hardware functions
implemented in programmable logic. This library can be linked into applications using the
standard GCC linker for Zynq®-7000 SoC and Zynq® UltraScale+™ MPSoC devices.
In addition to the library, sds++
generates a
complete boot image for the hardware functions and data motion network, including an FPGA
bitstream. Using this library, you can develop software applications that call the hardware
functions (and fixed hardware) using standard GCC toolchains. You are still targeting the same
hardware system and using the sds++
-generated boot
environment, but you are free to develop your software application using the GNU toolchain in
the software development environment of your choice.
Building a Shared Library
To build a shared library, sds++
requires at
least one accelerator. The following example provides three entry points into two hardware
accelerators: a matrix multiplier and a matrix adder. You can find these files in the
samples/libmatrix/build directory.
- mmult_accel.cpp: Accelerator code for the matrix multiplier
- mmult_accel.h: Header file for the matrix multiplier
- madd_accel.cpp: Accelerator code for the matrix adder
- madd_accel.h: Header file for the matrix adder
- matrix.cpp: Code that calls the accelerators and determines the data motion network
- matrix.h: Header file for the library
The matrix.cpp file contains functions
that define the accelerator interfaces as well as how the hardware functions communicate with
the platform (that is, the data motion networks between platform and accelerators). The
function madd
calls a single matrix adder accelerator, and
the function mmult
calls a single matrix multiplier
accelerator. Another function mmultadd
is implemented using
two hardware functions, with the output of the matrix multiplier connected directly to the
input of the matrix adder.
/* matrix.cpp */
#include "madd_accel.h"
#include "mmult_accel.h"
void madd(float in_A[MSIZE*MSIZE], float in_B[MSIZE*MSIZE], float out_C[MSIZE*MSIZE])
{
madd_accel(in_A, in_B, out_C);
}
void mmult(float in_A[MSIZE*MSIZE], float in_B[MSIZE*MSIZE], float out_C[MSIZE*MSIZE])
{
mmult_accel(in_A, in_B, out_C);
}
void mmultadd(float in_A[MSIZE*MSIZE], float in_B[MSIZE*MSIZE], float in_C[MSIZE*MSIZE],
float out_D[MSIZE*MSIZE])
{
float tmp[MSIZE * MSIZE];
mmult_accel(in_A, in_B, tmp);
madd_accel(tmp, in_C, out_D);
}
The matrix.h file defines the function interfaces to the shared library and is included in the application source code.
/* matrix.h */
#ifndef MATRIX_H_
#define MATRIX_H_
#define MSIZE 16
void madd(float in_A[MSIZE*MSIZE], float in_B[MSIZE*MSIZE], float out_C[MSIZE*MSIZE]);
void mmult(float in_A[MSIZE*MSIZE], float in_B[MSIZE*MSIZE], float out_C[MSIZE*MSIZE]);
void mmultadd(float in_A[MSIZE*MSIZE], float in_B[MSIZE*MSIZE], float in_C[MSIZE*MSIZE],
float out_D[MSIZE*MSIZE]);
#endif /* MATRIX_H_ */
In the samples/libmatrix/build/shared
folder, the Makefile
shows how the project is built by
specifying that the functions mmult_accel
, madd
, and mmult_add
must be
implemented in programmable logic.
SDSFLAGS = \
-sds-pf ${PLATFORM} \
-sds-hw mmult_accel mmult_accel.cpp -sds-end \
-sds-hw madd_accel madd_accel.cpp -sds-end
Object files are generated with position independent code (PIC), like
standard shared libraries, using the GCC standard -fpic
option:
sds++ ${SDSFLAGS} -c -fpic –o mmult_accel.o mmult_accel.cpp
sds++ ${SDSFLAGS} -c -fpic –o madd_accel.o madd_accel.cpp
sds++ ${SDSFLAGS} -c -fpic –o matrix.o matrix.cpp
Link the objects files by using the using the GCC standard –shared
switch:
sds++ ${SDSFLAGS} -shared -o libmatrix.so mmult_accel.o madd_accel.o matrix.o
After building the project, the following files are generated:
- libmatrix.so: Shared library suitable for linking using GCC and for runtime use
- sd_card: Directory containing an SD card image for booting the board
Delivering a Library
The following structure allows compiling and linking into applications using GCC in standard ways.
<path_to_library>/include/matrix.h
<path_to_library>/lib/libmatrix.so
<path_to_library>/sd_card
sd_card
folder is to be copied into an SD card and used to
boot the board. This image includes a copy of the libmatrix.so
file that is used at runtime.Compiling and Linking Against a Library
The following is an example of using the library with a GCC compiler. The library is used by including the header file matrix.h and then calling the necessary library functions.
/* main.cpp (pseudocode) */
#include "matrix.h"
int main(int argc, char* argv[])
{
float *A, *B, *C, *D;
float *J, *K, *L;
float *X, *Y, *Z;
...
mmultadd(A, B, C, D);
...
mmult(J, K, L);
...
madd(X, Y, Z);
...
}
To compile against a library, the compiler needs the header file. The path
to the header file is specified using the -I
switch. You
can find example files in the samples/libmatrix/use
directory.
gcc –I <path_to_library>/include –o main.o main.c
To link against the library, the linker needs the library. The path to
the library is specified using the -L
switch. Also, ask
the linker to link against the library using the -l
switch.
gcc –I <path_to_library>/lib –o main.elf main.o -lmatrix
For detailed information on using the GCC compiler and linker switches see the GCC documentation.
Use a Library at Runtime
At runtime, the loader looks for the shared library when loading the
executable. After booting the board into a Linux prompt and before executing the ELF
file, add the path to the library to the LD_LIBRARY_PATH
environment variable. The sd_card
created when building the library already has the library, so the
path to the mount point for the sd_card
must be
specified.
For example, if the sd_card
is mounted
at /mnt
, use this command:
export LD_LIBRARY_PATH=/mnt
Exporting a Shared Library
The following steps demonstrate how to export an SDSoC environment shared library with the corresponding SD card boot image using the SDSoC environment GUI.
- Select New SDx Library Project dialog box. to bring up the
- Create a new SDx Library project.
- Type
libmatrix
in the Project name field. - Specify the Location.
- Click Next.
- Check the Shared Library checkbox in the Accelerated Library Type window.
- Click Next.
- Select Platform to be
zc102
. - Click Next.
- Type
- Provide the system configuration and software details of your
project.
- Accept the default values in the System
Configuration dialog box.Note: Ensure that Sysroot path is unchecked.
- Click Next.
- Accept the default values in the System
Configuration dialog box.
- In the Templates dialog box, select Matrix Shared Library from the Available Templates, and click Finish to create the project.
- In the Project Explorer,
right-click
libmatrix
and select Import Sources. - In the Import Source dialog box,
select Browse and
samples/libmatrix
and selectbuild
and click OK. - In the Import Sources dialog
box, check
build
and click Finish.A new SDSoC shared library application project called
libmatrix
is created in the Project Explorer view. The project includes two hardware functionsmmult_accel
andmadd_accel
that are visible in the SDSoC Project Overview. - Build the library.
- In the Project Explorer view,
select the
libmatrix
project. - Select
After the build completes, there is a boot SD card image under the Debug (or current configuration) folder.
.
- In the Project Explorer view,
select the