2.编写头文件.h
一个库必须申明一个函数原型,而这个函数原型需要映射在一个头文件里面,在应用程序中,我们可以使用#include来调用这个头文件。一个头文件主要包括原函数的申明和pragma。下面,我以xilin的例程来讲解如何编写申明原函数和pragma。
函数申明如下所示,需要强调指出的是,这里必须指出传输数据的数量。
int arraycopy_aximm(int a[N], int b[N], int M);
pragma需要在函数申明之前写入,下面来介绍一些主要的progma:
1.SDS data data_move
该pragma是用来约束应用程序和IP之间的数据移动网络,对于一个变量,sdsoc是通过axi_lite来进行传输,对于数组,选择具体的数据传输方式需要在性能和资源上做权衡,应用程序和IP之间的数据移动网络如下图所示:
需要指出的是,axi_dma_simple是最高效的,但最多支持8 MB传输,因此仅适用于较大的传输,axi_fifo不需要与DMA一样多的硬件资源,但是由于其传输速率较慢,因此仅对于最大300字节的数据才是首选,axi_dma_sg提供了较慢的DMA性能,消耗了更多的硬件资源,但限制较少,并且在没有任何编译指示的情况下,通常是最好的默认数据移动器。
2. SDS data copy|zero_copy
SDSoC™环境会根据参数类型和以下data copy编译指示自动推断每个硬件功能参数的硬件接口类型,默认情况下,通过复制数据来传输硬件功能的数组参数,即等同于使用#pragma SDS data copy。因此,必须将数组参数用作输入或将其生成,但不能两者都使用。对于由硬件功能读取和写入的数组,必须使用#pragma SDS数据zero_copy告知编译器该数组应保留在共享内存中,而不要复制。
3. SDS data mem_attribute
对于支持虚拟内存的Linux之类的操作系统,将对用户空间分配的内存进行分页,这可能会影响系统性能。 SDSoC运行时还提供API来分配物理上连续的内存。 该编译指示可以用来告诉编译器参数是否已在物理上连续的内存中分配。该编译指令只用方法如下:
#pragma SDS data mem_attribute(ArrayName:contiguity)
ArrayName必须是函数定义的形参,contiguity必须是PHYSICAL_CONTIGUOUS和NON_PHYSICAL_CONTIGUOUS两者之一,默认的是NON_PHYSICAL_CONTIGUOUS,PHYSICAL_CONTIGUOUS对应于sds_alloc分配的内存,NON_PHYSICAL_CONTIGUOUS对应于malloc分配的内存。
更详细的信息大家可以参考xilinx的文档UG1027和UG1146。
下面是xilinx例程里面头文件的源码:
#ifndef ARRAYCOPY_H_
#define ARRAYCOPY_H_
#define N 32
#pragma SDS data data_mover(A:AXIDMA_SIMPLE, B:AXIDMA_SIMPLE)
#pragma SDS data copy(A[0:M])
#pragma SDS data copy(B[0:M])
int arraycopy_axis(int A[N], int B[N], int M);
#pragma SDS data zero_copy(a[0:M], b[0:M])
int arraycopy_aximm(int a[N], int b[N], int M);
#endif /* ARRAYCOPY_H_ */