要综合:
1)C 函数必须包含设计的全部功能
2)系统调用操作系统无法执行任何功能
3)C 构造必须具有固定或有界大小
4)这些结构的实现必须是明确的
1.Vivado HLS忽略仅显示数据且对算法执行没有影响的常用系统调用,通常,这些对系统的调用不能被综合,应该在综合之前从函数中删除,如 printf、 fprintf、getc()、time()、sleep()。
2.Vivado HLS 在执行综合时定义宏__SYNTHESIS__,从而在设计中排除不可综合的代码,这是一种方便的方法,可以在不从 C 函数中删除代码的情况下排除不可综合的代码。 使用这样的宏确实意味着用于模拟的 C 代码和用于综合的 C 代码现在是不同的
注意:1)仅在要综合的代码中使用__SYNTHESIS__宏,不要在测试平台中使用此宏,因为C 仿真或 C RTL 协同仿真不遵守。
2)不要使用__SYNTHESIS__宏来更改功能。 如果__SYNTHESIS__宏用于更改 C 代码的功能,则可能导致 C 模拟和 C 综合之间的结果不同, 此类代码中的错误本质上难以调试。
在下面的例子中,宏__SYNTHESIS__用于确保在综合期间忽略不可综合的文件写入:
#ifndef __SYNTHESIS__
FILE *fp1;// The following code is ignored for synthesis
char filename[255];
sprintf(filename,Out_apb_%03d.dat,apb);
fp1=fopen(filename,w);
fprintf(fp1, %d \n, apb);
fclose(fp1);
#endif
1.任何管理系统内存分配的系统调用,如malloc(),alloc()和 free(),都使用操作系统内存中存在的资源,并在运行时创建和释放:
1)要合成硬件实现,设计必须完全自包含,指定所有必需的资源。
2)必须在综合之前从设计代码中删除内存分配系统调用。由于动态内存操作用于定义设计的功能,因此必须将它们转换为等效的有界表示。
例:下面的代码演示了如何将使用 malloc()的设计转换为可综合的版本,并重点介绍两种有用的coding style:
a.不使用__SYNTHESIS__宏。 定义宏 NO_SYNTH 用于在可合成和不可综合的版本之间进行选择,这确保了在 C 中模拟本来的代码并且可在 Vivado HLS 中综合。
b.使用了malloc()的原始设计中的指针,不需要重写以使用固定大小的元素,该技术可以防止对现有设计进行手动重新编码。
#include "malloc_removed.h"
#include
//#define NO_SYNTH
dout_t malloc_removed(din_t din[N], dsel_t width) {
#ifdef NO_SYNTH
long long *out_accum = malloc (sizeof(long long));
int* array_local = malloc (64 * sizeof(int));
#else
long long _out_accum;
long long *out_accum = &_out_accum;
int _array_local[64];
int* array_local = &_array_local[0];
#endif
int i,j;
LOOP_SHIFT:for (i=0;i<N-1; i++) {
if (i<width)
*(array_local+i)=din[i];
else
*(array_local+i)=din[i]>>2;
}
*out_accum=0;
LOOP_ACCUM:for (j=0;j<N-1; j++) {
*out_accum += *(array_local+j);
}
return *out_accum;
}
由于此处的编码更改会影响设计的功能,因此 Xilinx 不建议使用 __SYNTHESIS__宏
2.与 C 中动态内存使用的限制一样,Vivado HLS 不支持(用于综合)动态创建或销毁的C ++对象,这包括动态多态和动态虚函数调用。
无法综合以下代码,因为它在运行时创建新函数:
Class A {
public:
virtual void bar() {…};
};
void fun(A* a) {
a->bar();
}
A* a = 0;
if (base)
a = new A();
else
a = new B();
foo(a);
注:virtual:虚函数 ,new:开辟一个新的存储空间
递归函数无法综合。
1)这适用于可以形成无限递归的函数,其中无穷无尽:
unsigned foo (unsigned n)
{
if (n == 0 || n == 1) return 1;
return (foo(n-2) + foo(n-1));
}
(函数foo无限递归)
2)Vivado HLS 不支持尾递归,其中存在有限数量的函数调用。
unsigned foo (unsigned m, unsigned n)
{
if (m == 0) return n;
if (n == 0) return m;
return foo(n, m%n);
}
注:当递归调用是整个函数体中最后执行的语句且它的返回值不属于表达式(m%n)的一部分时,这个递归调用就是尾递归。在尾递归中,首先执行表达式的计算,然后执行递归调用,将当前步骤的结果传递给下一个递归步骤。
许多 C++标准模板库(STL)包含函数递归并使用动态内存分配。因此,无法综合STL。使用 STL 的解决方案是创建具有相同功能的本地函数,则该本地函数不具有递归、动态内存分配或动态创建和销毁对象的这些特性。
注意:合综合支持标准数据类型,例如 std :: complex
注:本文基于Vivado 设计套件用户指南-----高层次综合,在翻译的基础上结合自己的理解与思考后整理而得