理解Vitis HLS默认行为-Xilinx-AMD社区-FPGA CPLD-ChipDebug

理解Vitis HLS默认行为

相比于Vivado HLSVitis HLS更加智能化,这体现在Vitis HLS可以自动探测C/C++代码中可并行执行地部分而无需人工干预添加pragma。另一方面Vitis HLS也会根据用户添加的pragma来判断是否需要额外配置其他pragma以使用户pragma生效。为便于说明,我们来看一个简单的案例。
如下图所示代码,函数array_mult用于计算两个一维数组对应元素差的平方。数组长度为N,故通过Nfor循环可完成此操作(这里N8)。
图片[1]-理解Vitis HLS默认行为-Xilinx-AMD社区-FPGA CPLD-ChipDebug
如果我们不添加任何pragma,从C综合后的报告来看,工具会自动对for循环添加PIPELINE,如下图所示。同时,工具会将数组映射为单端口RAM(因为数组是顶层函数的形参,故只生成单端口RAM需要的端口信号),这样匹配了DSP48的接口需求(两个输入数据一个输出数据)。从C/RTL Cosim的波形可以看到输入/输出数据流关系。
图片[2]-理解Vitis HLS默认行为-Xilinx-AMD社区-FPGA CPLD-ChipDebug
图片[3]-理解Vitis HLS默认行为-Xilinx-AMD社区-FPGA CPLD-ChipDebug
如果我们对for循环施加UNROLL,理论上分析可知工具应将for循环展开(复制8份),这样会消耗8DSP48,如下图所示。这就需要能同时有16个数据提供给这8DSP48,但此时工具只是将数组映射为双端口RAM。这显然造成了数据通路的不匹配。这其实造成了DSP48的浪费。这里,因为数组是顶层函数,故工具并没有对其施加ARRAY_PARTITION,但如果是子函数的形参,工具就会自动对数组施加ARRAY_PARTITION,以确保数据通路的匹配。
图片[4]-理解Vitis HLS默认行为-Xilinx-AMD社区-FPGA CPLD-ChipDebug
因此,我们换个思路,既然工具至多会将数组映射为双端口RAM,那么我们就将for循环复制两份,从而实现数据通路的匹配。这可通过UNROLL的选项factor设置为2。从C综合报告来看,消耗了2DSP48,同时工具对for循环自动设置了PIPELINE
图片[5]-理解Vitis HLS默认行为-Xilinx-AMD社区-FPGA CPLD-ChipDebug
图片[6]-理解Vitis HLS默认行为-Xilinx-AMD社区-FPGA CPLD-ChipDebug
当然,我们也可以对整个函数施加PIPELINE,这样工具会将for循环自动UNROLL,但这同样会造成DSP48的浪费,因为工具不会对顶层函数的形参数组自动进行ARRAY_PARTITION。于是,我们考虑手工添加ARRAY_PARTITION,同时对函数添加PIPELINE,从而使得数据通路完美匹配。
图片[7]-理解Vitis HLS默认行为-Xilinx-AMD社区-FPGA CPLD-ChipDebug

 

 

请登录后发表评论

    没有回复内容