Exporting a Library for GCC
This chapter demonstrates how to use thesds++
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 forZynq®-7000 SoCandZynq® UltraScale+™ MPSoCdevices.
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 thesds++
-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 thesamples/libmatrix/builddirectory.
- 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
Thematrix.cppfile 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 functionmadd
calls a single matrix adder accelerator, and the functionmmult
calls a single matrix multiplier accelerator. Another functionmmultadd
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); }
Thematrix.hfile 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 thesamples/libmatrix/build/sharedfolder, theMakefile
shows how the project is built by specifying that the functionsmmult_accel
,madd
, andmmult_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.
/include/matrix.h /lib/libmatrix.so /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 filematrix.hand 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 thesamples/libmatrix/usedirectory.
gcc –I /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 /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 theLD_LIBRARY_PATH
environment variable. Thesd_card
created when building the library already has the library, so the path to the mount point for thesd_card
must be specified.
For example, if thesd_card
is mounted at/mnt
, use this command:
export LD_LIBRARY_PATH=/mnt
Exporting a Shared Library
The following steps demonstrate how to export anSDSoCenvironment shared library with the corresponding SD card boot image using theSDSoCenvironment GUI.
- SelectNew SDx Library Projectdialog box. to bring up the
- Create a new SDx Library project.
- Type
libmatrix
in theProject namefield. - Specify theLocation.
- ClickNext.
- Check theShared Librarycheckbox in theAccelerated Library Typewindow.
- ClickNext.
- SelectPlatformto be
zc102
. - ClickNext.
- Type
- Provide the system configuration and software details of your project.
- Accept the default values in theSystem Configurationdialog box.
Note:Ensure that Sysroot pathis unchecked.
- ClickNext.
- Accept the default values in theSystem Configurationdialog box.
- In theTemplatesdialog box, selectMatrix Shared Libraryfrom the Available Templates, and clickFinishto create the project.
- In theProject Explorer, right-click
libmatrix
and selectImport Sources. - In theImport Sourcedialog box, selectBrowseand
samples/libmatrix
and selectbuild
and clickOK. - In theImport Sourcesdialog box, check
build
and clickFinish.A newSDSoCshared library application project called
libmatrix
is created in theProject Explorerview. The project includes two hardware functionsmmult_accel
andmadd_accel
that are visible in theSDSoC Project Overview. - Build the library.
- In theProject Explorerview, select the
libmatrix
project. - Select
After the build completes, there is a boot SD card image under the Debug (or current configuration) folder.
.
- In theProject Explorerview, select the