为串流数据使用 HLS 串流 - 2021.2 Chinese

Vitis 高层次综合用户指南 (UG1399)

Document ID
UG1399
Release Date
2021-12-15
Version
2021.2 Chinese

对早期代码可执行的首要改进措施之一是使用 HLS 串流构造(通常称为 hls::stream)。hls::stream 对象可采用与阵列相同的方式来存储数据采样。hls::stream 中的数据只能按顺序访问。在 C/C++ 语言代码中,hls::stream 的行为与无限深度的 FIFO 相似。

使用 hls::stream 编写的代码通常用于在 FPGA 中创建设计,此类设计性能高且占用资源极少,因为 hls::stream 会强制使用最适合 FPGA 中实现的编码样式。

无法从 hls::stream 多次读取相同数据。从 hls::stream 中读取数据后,该数据在串流中就不再存在。这有助于消除此编码实践。

如果需要再次使用 hls::stream 中的数据,则需将其置于高速缓存中。对于编写将在 FPGA 上进行综合的代码,这是另一项非常实用的实践。

hls::stream 会强制以适合 FPGA 实现的方式来开发 C/C++ 语言代码。

hls::stream 进行综合后,它会作为 FIFO 通道来自动实现,深度为 1 个元素。这是适合连接已流水打拍的任务的理想硬件。

无需使用 hls::stream,并且可使用 C/C++ 语言代码中的阵列来执行相同的实现。hls::stream 构造有助于强制实施正确的编码实践。

对于 hls::stream 构造,经过最优化的新代码大纲如下所示:

template<typename T, int K>
static void convolution_strm(
int width, 
int height,
hls::stream<T> &src, 
hls::stream<T> &dst,
const T *hcoeff, 
const T *vcoeff)
{

hls::stream<T> hconv("hconv");
hls::stream<T> vconv("vconv");
// These assertions let HLS know the upper bounds of loops
assert(height < MAX_IMG_ROWS);
assert(width < MAX_IMG_COLS);
assert(vconv_xlim < MAX_IMG_COLS - (K - 1));

// Horizontal convolution 
HConvH:for(int col = 0; col < height; col++) {
 HConvW:for(int row = 0; row < width; row++) {
   HConv:for(int i = 0; i < K; i++) {
 }
 }
}
// Vertical convolution 
VConvH:for(int col = 0; col < height; col++) {
 VConvW:for(int row = 0; row < vconv_xlim; row++) {
   VConv:for(int i = 0; i < K; i++) {
 }
}

Border:for (int i = 0; i < height; i++) {
 for (int j = 0; j < width; j++) {
 }
}

相比于早期代码,值得注意的明显差异包括:

  • 输入和输出数据现已采用 hls::stream 来建模。
  • 其中并不采用大小为 HEIGHT*WDITH 的单一局部阵列,而是改为使用 2 个内部 hls::stream 来保存水平和垂直卷积的输出。

此外,部分 assert 语句用于指定循环边界的最大值。这是非常实用的编码样式,允许 HLS 自动报告变量边界循环的时延并最优化循环边界。