目录
Utilization Estimates (资源使用率估计)
前言
哈喽各位同学大家好,前一篇文章中,我们介绍了HLS的一些基础知识,以及Vivado HLS的工程结构和主界面等,本节我们就以官方UG871中的一个实例来体会HLS设计的落地过程。
学习目标
- 使用 Tcl脚本文件启动 Vivado HLS。
- 学会查看Vivado HLS综合报告。
- 实战体会一遍HLS设计流程。
- 创建不同的Solution,并比较不同Solution之间的区别,体会HLS的优化功能。
工程代码获取
各位请点击本链接,下载Xilinx官方的示例包。本工程位于“Introduction\lab3”文件夹中。
- fir.c :本工程的Top Function文件,算法核心
- fir.h:本工程使用的头文件
- fir_test.c:本工程的TestBench
- out.gold.dat:本工程的黄金参考
- run_hls.tcl:本工程的脚本文件,使用该文件我们可以在命令行中打开HLS工程
TopFunction代码分析
头文件
#ifndef FIR_H_
#define FIR_H_
#define N 11
typedef int coef_t;
typedef int data_t;
typedef int acc_t;
void fir (
data_t *y,
coef_t c[N+1],
data_t x
);
#endif
头文件中最关键的是定义了变量类型
TopFunction文件
#include "fir.h" //引用头文件
//定义模块
void fir (
data_t *y,
coef_t c[N],
data_t x
) {
static data_t shift_reg[N];
acc_t acc;
data_t data;
int i;
acc=0;
Shift_Accum_Loop: for (i=N-1;i>=0;i--) {
if (i==0) {
shift_reg[0]=x;
data = x;
} else {
shift_reg[i]=shift_reg[i-1];
data = shift_reg[i];
}
acc+=data*c[i];;
}
*y=acc;
}
这个Function的组成包括了一个for循环(Shift_Accum_Loop)和内部的一个if判断以及相乘相加操作,最后再进行赋值。大家可能很好奇,这个Function没有Return,那么它是如何判断输入和输出端口的呢?
其实HLS能对这个端口进行自行判断,被赋值的数值作为输出,而用来赋值的数就是输入。
设计目标
- 设计一个高吞吐量的设计版本。
- 最终的设计应该能够处理带有输入有效信号指示的数据。
- 产生输出数据并且有输出有效信号。
- 滤波器系数被存储到FIR设计的外部,使用一个单端口内存存储。
使用Tcl创建Vivado HLS工程
大家可以看到,我们的源文件夹里是没有工程文件存在的,因此需要我们进行创建。这里我要提醒大家:文件路径不要有中文!!!
- 打开 Vivado HLS Conmmand Prompt
- 使用Cd命令切换到Tcl文件所在地址,并且输入“vivado_hls -f run_hls.tcl”创建工程
- 随后输入:“vivado_hls -p fir_prj”来打开工程界面
- 可以看到左侧的导航窗口,各个文件排放正确:
这是因为Tcl文件中包含了创建工程和放置文件的各项脚本:
# Create a Vivado HLS project
open_project -reset fir_prj
set_top fir
add_files fir.c
add_files -tb out.gold.dat
add_files -tb fir_test.c
# Solution1 *************************
open_solution -reset "solution1"
set_part {xcvu9p-flgb2104-1-e}
create_clock -period 10
# Run C simulation
csim_design
# Run Synthesis
csynth_design
# Run RTL verification
cosim_design
# Create the IP package
export_design
exit
查看综合报告
Timing
我们首先来看Timing这个栏目:
- Clock :即该模块使用的时钟,这里叫ap_clk
- Target:目标的最小时钟周期,这里是10ns,也就是100MHz
- Estimated:预估最坏路径下的时钟周期,这里为5.772ns
- Uncertainty:时钟的不确定性,确保了由于布局和路线而导致的未知的净延迟可以有一定的时间余地
一般情况下,我们实际目标周期 等于 目标周期 减去 不确定时间 ,而Estimated是Solution综合之后预估的最小周期,如果比实际目标周期大,那么就意味这不符合要求。例如
Latency(clock cycles)
Summary
这一栏主要是对整个模块的一个总结,Latency代表延迟,代表输入数据到输出数据的时间间隔,单位为时钟周期,Interval代表两次输入之间的间隔。
从上图我们可以得出一个结论:该模块不存在流水线结构。原因是两次输入之间的间隔等于数据输入到输出的延迟。也也就意味着,要等上一次的结果输出之后才能输入下一个数据。也就代表着模块不是流水线结构。
Detail
Detail栏目里面又分有很多的子项,当然,看法和前面说的Summary差不多:
- Instance:该栏目展示子模块的延迟信息,本节例子没有子模块,因此不显示。、
- Loop:该栏目展示模块中的循环信息,可以看到包含一个叫做:Shift_Accum_Loop的循环,循环执行11次(Trip Count代表循环执行次数),每次循环需要的时间是3个时钟周期(Iteration Latency是循环执行一次所需要的时间),因此总共需要33个时钟周期(Latency),另外还有一些其它的栏目,例如Pipeline显示了流水线信息等。
Utilization Estimates (资源使用率估计)
这个栏目是统计资源利用率的,类似前面的Latency,也有分为Summary和Detail两个子项,Summary里进行总体的估计,Detail是各个子模块,循环等等的使用率,这个栏目比较简单不用多说。
值得注意的是,这里的数目只是一个估计的值,因为在RTL综合时有可能会增加一些优化选项,在综合之后表上的数据可能会发生变化。
Interface
该栏目展示了接口综合器生成的端口和IO控制协议:
- 本设计有一个时钟信号线和复位信号线(ap_clock和ap_reset)这些端口和设计模块本身有关系
- 同时,接口综合器也添加了许多模块级别的控制接口,例如ap_start,ap_done,ap_idle,ap_ready等等。
- 模块的输出端口被综合成了一个32位的数据接口,并且还带有一个有效信号 y_ap_vld
- 模块的输入参数c(一个数组)被综合成了一个访问 block RAM的接口,有一个四位的地址信号,和一个片选信号以及一个32位的数据口。
- 最后,输入的标量x被综合成了一个没有任何控制协议的数据端口:ap_none
至此,HLS综合报告的介绍到此基本结束了,在后面一节我们将继续一步步地演示一个HLS工程开发的全过程。