思考空间
对于如图11所示的顶层函数,HLS会将其接口综合成何种形式?
对于顶层函数,如果形参类型为hls::stream,HLS会将其综合为ap_fifo类型的接口。
这里,我们看一个HLS Stream应用案例。顶层函数top由两个底层函数read_data和handle_data构成,其中read_data主要功能是从输入stream上获取特定数据;handle_data的主要功能则是对获取的数据进行处理。这里主要是为了说明stream的使用方法,所以,请大家把关注点放在stream的定义、函数之间的参数传递以及相应的directive的设置等。实际上,read_data和handle_data是可以合并的。
从图2和图3的代码中可以看到,从流中读取数据可以用>>或read(),向流中写入数据可以用 << 或write()。同时,在使用 << 或 >> 时,并不需要添加#include <iostream>。
首先,执行C功能仿真,仿真结束时会出现如图5所示的warning。
第二步,不设置任何directive,直接执行C综合,此时会显示如下错误信息。该信息表明,在非dataflow区域使用默认的FIFO规模(这个FIFO是因为stream而生成的,默认深度为1),会导致Deadlock。根据提示我们修改这个FIFO的深度。之后,重新执行C综合和C/RTL Cosimulation,均可通过。
第三步,进一步优化,可以看到这两个底层函数是可以应用dataflow以降低latency。具体设置如图7所示。执行C综合,综合结束时会显示如图8所示信息。[HLS214-111]显示静态变量和非静态Stream不能在同一个DATAFLOW区域中使用,故需要对top.cpp第4行进行修改,只需添加static关键字,如图9所示。再次综合,该warning即被消除。
如果只设置DATAFLOW,而不设置FIFO深度,C综合是可以通过的,但执行C/RTL Cosimulation时,会显示如图10所示错误信息。可以判断与FIFO的读写相关。这通常是因为出现了FIFO写满或者FIFO读空,从而造成DEADLOCK。从这个角度而言,先设置一个solution,不用进行任何directive的设置,执行C综合,尽可能地修复所有的warning。这个阶段给出的warning及修复建议更具体、更具有针对性。
第四步,进一步优化,由于数组key深度只有8,可以完全打散,用register代替,具体设置如图11所示。
至此,我们创建了3个Solution:
Solution 1: 设置FIFO深度
Solution 2: 设置FIFO深度 设置DATAFLOW
Solution 3: 设置FIFO深度 设置DATAFLOW ARRAY PARTITION
3个Solution综合后的性能对比如图12所示。
从这个案例我们可以得出如下结论:
-流用于内部函数间的参数传递时,会被综合为深度为1的FIFO
-当流数据被综合为FIFO时,由于默认深度为1,可能会在C/RTLCosimulation时出现DEADLOCK
-先创建一个没有任何directive的Solution执行C综合,尽可能地解决此时出现的warning或者错误,这也是UFDM所倡导的设计思想。
思考空间
如果要修改hls_stream对应的FIFO的深度,该采用哪个directive?