C-Callable Library Examples

You can find examples of Vivado tools-packaged RTL IP that can be compiled as C-callable libraries in the samples/rtl directory of the SDx software installation. These example include aximm_arraycopy, axis_arraycopy, and count.

In each of these examples there are three folders:
  • app: Contains the top-level application example that uses the function from the C-callable library.
  • ip: Contains the RTL IP for packaging by the Vivado Design Suite, that defines the hardware function.
  • src: Contains the header definition (.h/.hpp) file for the software function.
The arraycopy_aximm and count examples contain a Makefile that can be run in order, as well as a top-level Makefile that can be used to run all three of the individual Makefiles. The order of operations to define the C-callable library is:
  1. Create the packaged RTL IP using the Vivado Design Suite by running the ../ip/Makefile. This makefile creates the component.xml for the packaged IP that is required for the sdx_pack utility.
  2. Create the C-callable library object and archive by running the ../src/Makefile. This makefile uses sdx_pack to create the C-Callable library archive, and copies the needed files into the ../lib and ../inc folders.
  3. Compile the top-level application by running the ../app/Makefile. This makefile uses the sdscc/sds++ compiler to compile the main application, linking to the C-callable library.

To build the sample applications open an SDx Terminal window, change directory to the specific example, ../samples/rtl/aximm_arraycopy folder for example, and run the top-level make file, or run each separate make file in the sequence described above.

TIP: The makefiles run on Linux as written. To run on the Windows Operating System you must remove the comment lines beginning with #, and edit the mkdir command to remove the -p option and use the '\' character. An edited Makefile for the aximm_arraycopy/src folder is shown below:
DEP_FILES = arraycopy.hpp
OBJ_FILES = arraycopy.o

all: $(DEP_FILES) $(OBJ_FILES)
	arm-none-eabi-ar crs libarraycopy.a arraycopy.o

	rm -rf ../lib
	mkdir ..\lib
	cp libarraycopy.a ../lib

	rm -rf ../inc
	mkdir ..\inc
	cp arraycopy.hpp ../inc

$(OBJ_FILES): $(DEP_FILES)
	sdx_pack -func arraycopy -header arraycopy.hpp -ip ../ip/component.xml \
     -control AXI=s_axi_axilite:0 -map input=s_axi_axilite:in:0x10,m_axi_copy_in:in \
     -map output=s_axi_axilite:in:0x18,m_axi_copy_out:out -map qty=s_axi_axilite:in:0x20 \
     -target-os standalone -verbose

clean:
	rm -rf _sds .Xil
	rm -rf libarraycopy.a
	rm -rf sdx_pack.*

ultraclean: clean
	rm -rf $(OBJ_FILES
The arraycopy examples contain two IP cores, each of which copies M elements of an array from its input to its output, where M is a scalar parameter that can vary with each function call.
  • arraycopy_aximm - array transfers using an AXI master interface in the IP.
  • arraycopy_axis - array transfers using AXI4-Stream interfaces.

The register mappings for the IPs are as follows.

// arraycopy_aximm
// 0x00 : Control signals
// bit 0 - ap_start (Read/Write/COH)
// bit 1 - ap_done (Read/COR)
// bit 2 - ap_idle (Read)
// bit 3 - ap_ready (Read)
// bit 7 - auto_restart (Read/Write)
// others - reserved
// 0x10 : Data signal of ap_return
// bit 31~0 - ap_return[31:0] (Read)
// 0x18 : Data signal of a
// bit 31~0 - a[31:0] (Read/Write)
// 0x1c : reserved
// 0x20 : Data signal of b
// bit 31~0 - b[31:0] (Read/Write)
// 0x24 : reserved
// 0x28 : Data signal of M
// bit 31~0 - M[31:0] (Read/Write)
// 0x2c : reserved
// (SC = Self Clear, COR = Clear on Read, TOW = Toggle on Write, COH = Clear on Handshake)

// arraycopy_axis
// 0x0 : Control signals
// bit 0 - ap_start (Read/Write/COH)
// bit 1 - ap_done (Read/COR)
// bit 2 - ap_idle (Read)
// bit 3 - ap_ready (Read)
// bit 7 - auto_restart (Read/Write)
// .
// .
// .
// 0x10 M[31:0] (Read/Write)
// (COR = Clear on Read, COH = Clear on Handshake