将TestMatrixMultiply.c内容改为:[cpp]
#include
typedef int data_type;
#define N 5
const data_type MatrixA[] = {
#include "A.h"
};
const data_type Vector_b[] = {
#include "b.h"
};
const data_type MatlabResult_c[] = {
#include "c.h"
};
data_type HLS_Result_c[N] = {0};
void CheckResult(data_type * matlab_result,data_type * your_result);
int main(void)
{
printf("Checking Results: ");
MatrixMultiply(MatrixA,Vector_b,HLS_Result_c);
CheckResult(MatlabResult_c,HLS_Result_c);
return 0;
}
void CheckResult(data_type * matlab_result,data_type * your_result)
{
int i;
for(i = 0;i
{
printf("Idx %d: Error = %d
",i,matlab_result[i]-your_result[i]);
}
}
首先进行C语言仿真验证,点这个按钮:
结果如下:
从C仿真输出看到,仿真结果与matlab计算结果一致,说明我们编写的C程序MatrixMultiply是正确的。接下来进行综合,按C仿真后面那个三角形按钮,得到结果如下:
注意到,计算延迟为186个时钟周期。这是未经过优化的版本,记为版本1。为了提高FPGA并行计算性能,我们接下来对它进行优化。打开MatrixMultiply.c,点Directives页面,可以看到我们可以优化的对象。
注意到矩阵和向量相乘是双层for循环结构。我们先展开最内层for循环,步骤如下:右键点击最内侧循环,右键,然后Insert Directive...
弹出对话框如下,Directives选择UNROLL,OK即可,后面所有都保持默认。
再次综合后,结果如下
可见效果非常明显,延迟缩短到51个时钟周期。用同样方法,展开外层循环,综合后结果如下:
计算延迟又降低了1/3!!!可是代价呢?细心的你可能发现占用资源情况发生了较大变化,DSP48E1由最初的4个变为8个后来又成为76个!!!FPGA设计中,延迟的降低,即速度提高,必然会导致面积的增大!循环展开是优化的一个角度,另一个角度是从资源出发进行优化。我们打开Analysis视图,如下所示:
从分析视图可以看出各个模块的运行顺序,从而为优化提供更为明确的指引。我们发现AA_load导致了延迟,如果所有AA的值都能一次性并行取出,势必会加快计算效率!回到Synthetic视图,为AA增加Directives:
选择Resources,再点Cores后面的方框,进入Vivado HLS core选择对话框
按上图进行选择。使用ROM是因为在计算矩阵和向量相乘时,AA为常数。确认。仍然选择AA,增加Directives,如下图:
选择数组分解,mode选择完全complete,综合后结果如下图:
延迟进一步降低,已经降到11个时钟周期了!!!是否已经达到极限了呢???答案是否定的。我们进入Analysis视图,看一下还有哪些地方可以优化的。经过对比发现bb也需要分解,于是按照上面的方法对bb进行资源优化,也用ROM-2P类型,也做全分解,再次综合,结果如下:
发现延迟进一步降低到8个时钟周期了!!!老师,能不能再给力点?可以的!!!!我们进入分析视图,发现cc这个回写的步骤阻塞了整体流程,于是我们将cc也进行上述资源优化,只不过资源类型要变为RAM_2P,因为它是需要写入的。综合结果:
整体延迟已经降低到6个clk周期了!!!再看Analysis视图:
延迟已经被压缩到极限了。。。。老师,还能再给力点嘛?答案是可以的!!!!我们前面的所有运算都是基于整形数int,如果将数值精度降低,将大大节省资源。注意现在DSP48E1需要100个!看我们如何将资源再降下来。这就需要借助“任意精度”数据类型了。HLS中除了C中定义的char,shrot,int,long,long long 之外,还有任意bit长度的int类型。我们将代码开头的data_type定义改为:[cpp]
#include
typedef uint15 data_type;
评论
查看更多