Vivado HLS常用优化命令介绍

 

HLS 简介        

         Xilinx Vivado HLS工具可以将用户使用C++编写的逻辑自动转化为硬件语言(如Verilog或VHDL语言)编写的RTL级硬件逻辑,目的是为了让软件工程师将算法快速部署在FPGA上。但是目前,使用者在没有硬件基础的情况下仍难通过该工具将算法高效地部署。此过程中,用于制导的pragma优化命令的使用对最终RTL代码生成影响很大,有关各种优化命令的学习可以参考官方文档UG902和UG1270,这里讲一下较为常用的几个优化命令,分别是PIPELINE,UNROLL,ARRAY PARTITION

一、PIPELINE命令

        该命令经常在for循环中使用,旨在告诉编译器要对该循环下的代码做流水化处理。理想情况下流水线间隔(Initiation Interval)II=1,相当于一个cycle一个运算单元可以完成一个操作。至于该代码最终是否优化到1,则和实际代码中的数据依赖性和并行性有关。下面给出官方文档中的例子。

Vivado HLS常用优化命令介绍_第1张图片

        上面这个例子中,左侧是func()串行执行过程,右侧则是添加了PIELINE命令后的执行过程,该例子中,添加命令后流水线间隔II=1。一个cycle内WR,CMP,RD同时计算,产生一个结果。在N(loop counter)很大以及II=1时,该函数体的执行时间约等于N,即循环的次数。因此,该添加命令后,可以查看hls综合出的性能报告(Detail->Loop)下,其理想情况则是II=1,在后面的例子中会详解。毫无疑问,添加该命令会显著增加资源消耗,所以在多层for循环中,该命令通常放在最内层循环中,但也不尽然。

二、UNROLL命令

        该命令将for循环下循环体展开,硬件上则相当于将循环体复制了N(循环次数)份,每个循环体同时执行。下面仍以官方文档中的例子说明,可以对比一下和PIPELINE的区别。

Vivado HLS常用优化命令介绍_第2张图片

        上图中,Rolled Loop是未添加UNROLL命令的情况,其中假设一个cycle可以完成读b,读c,相加并写入a,则该循环需要4个周期。Partially Unrolled Loop这里是设置了factor=2,相当于将循环体分为两份展开,共需要2个cycles。最右侧则是完全展开的例子,仅需要一个cycles。以有右侧为例,在一个cycle中同时读出b[0~3],c[0~3] 四个加法,写c[0~3]。这里N=4,则a中的数据需要分别存储在4个单口BRAM中(这里就涉及到了矩阵划分),以在一个cycle提供4个数据,b,c同理。同时也需要N个加法器。可见UNROLL命令对资源的需求很大。

三、矩阵划分 Array Partition

        矩阵划分命令一般对矩阵使用。C语言中的int a[N] ;表示声明一个包含了N个元素的数组a,在hls中其实对应于在片上BRAM中给a分配N个元素的空间,但至于这N个元素在FPGA中怎么存储的,则可以通过array partition命令去指定。默认情况下,a中的元素连续存储在一块BRAM中,则一个cycle只能提供一个数据,而片上带宽往往需要很大,因此就需要使用该命令。

Vivado HLS常用优化命令介绍_第3张图片

        从上图可以看出,矩阵划分分为三个类型,分别为block、cyclic和complete。详细解释可以看官方说明书,这里粗略地讲一下。

  • block的意思为使用几块BRAM去存储该数组。上图的例子中设置factor=2,表示使用数组前半部分和后半部分分别存储在两块BRAM中,其中单块BRAM中元素都是连续存放的。
  • cyclic,就比较有意思了。设置factor=2,代表相邻的两个元素存储在不同的bram中,这里类似于内存交错手法。
  • complete则代表数组中的所有元素都是分别存放在不同的BRAM中。

同时由于数组可以有多个维度,通过设置dim=0/1/2/3来选择划分的维度。其中需要注意的是dim=0代表所有维度中的数据都完全离散。看下面这个图比较容易理解。

Vivado HLS常用优化命令介绍_第4张图片

先写这么多吧,HLS这个工具目前还在逐步完善,还是有硬件基础的人去写才行,但是由于是软件自动生成的RTL代码,控制起来就不如自己手写Verilog那么精确,但是好处在于快速实现。趁着假期在家没事儿写写,划划水。

你可能感兴趣的:(Vivado HLS常用优化命令介绍)