Vivado HLS优化总结

1,714 阅读4分钟

一、接口综合

1、一般接口

2、对数组的处理

当数组作为顶层函数的入参,不管是什么类型的都会被综合成ap_memory

3、其他案例

二、for循环优化方法总结

1、基础概念

下图是for循环顺序执行时的时钟图,每个方块代表一个时钟 循环次数是N=3,每次循环都有三步c1、c2、c3,也就是每个循环消耗三个时钟周期

2、for 循环优化之pipeline

Pipeline优化的原理就是,使II=1,for循环的N次循环间具有了并行性

3、Unroll

使用方法:其中的factor表示将for循环复制几份

4、loop merge

注意两个for循环的N是有限制的 原理是:由顺序执行,变成了并行

此种优化的限制: 边界不一致时,以最大的为边界

一个边界为变量,则会报错

两个for循环的边界都是变量,会报错

边界问题的解决方法:修改代码

5、Dataflow

5.1 问题的模型:注意三个task中的数组,只有一个是函数传入的,另外两个是函数中定义的

优化原理:通过在两个for循环之间添加channel增加了并行性

5.2 Dataflow使用限制即特殊情况的解决方法:

A、只有一个生产者,两个消费者

解决方案是:增加一个loop copy

B、bypass模型

解决方法:

6、嵌套循环的优化

嵌套循环分为四类场景,若要优化,需要尽可能将循环转换为perfect loop

A、perfect loop的优化

对外部做pipeline,内部的所有循环都会被打开;

对内部循环做流水,外部被打平flatten

B、Imperfect loop优化

对最内部的for循环做流水

由于有了res的初试化,所以外部循环不能完全flatten

对第二层for循环做流水

第二层以下的for循环都会被unroll,第一层会和第二层一起打平flatten,所以trip count是9

对第一层for循环做流水,最外层以下的都会被unroll

对函数进行流水线,则函数里面的所有for循环都会被unroll

对矩阵乘法的优化,添加缓冲区

矩阵乘法的原理 添加缓冲区的优化

7、for循环的其他优化方法

A、将for循环用函数包装,然后使用allocation优化,limit=2表示复制两份这个函数表示的电路

B、pipeline with rewind

是连续执行两次for循环时,两次for循环之间会有时延,使用rewind,可以减少此时间间隔,比如上面的例子中,连续执行两个函数打包的for循环

Rewind的限制:多个循环时,无法执行rewind

C、自动pipeline

D、pipeline失效的情景:循环边界是变量

三种解决办法:

循环变量类型声明为ap_int Assert限制循环变量的大小

三、数组的优化

数组最终都会以 memory 的形式实现(RAM、ROM 或 FIFO)。 如果这个数组作为顶层函数的形参,那么最终就会以相应的 memory 接口形式呈现,包括相应的读写地址和数据以及读写使能。 如果数组在设计内部,最终就会映射为真正的 block RAM,LUTRAM,UltraRAM或者 register,具体类型取决于在设计中使用的优化方法。 用 memory 或 memory ports 实现的数组往往是设计中的性能瓶颈。

1、数组的分割partition

Vivado HLS 提供了 3 种对数组分割的方法,分别是 block,cyclic 和 complete。 block 分割就是将数组元素分割为指定块数,然后依次填满每一块。Cyclic 方法就是分割为指定块数后先每块分配一个元素,然后每块分配第二个元素,直至分配完所有元素。Complete 方法就是每个元素分配一个寄存器存储。如图 20-1 所示:

对于多维数组,如下所示 例:

2、数组的map,不会提升吞吐率,但是可以减少资源使用量

3、针对同一个数组的array_reshape

Example

4、数组的其他优化方法

数组初始化 如果是映射为memorary,则要加static;如果是映射为rom,要加const

三、函数层面的优化

1、Inline

2、Allocation

3、Dataflow