一、接口综合
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