目录
前言
前一篇文章大致介绍了 Vitis 开发环境,那么接下来通过实现向量加法的简单 Hello World 进一步了解 Vitis 的 Host 和 Kernel 结构。
工程文件:Github - Hello World (HLS C/C++ Kernel)
代码分析:Kernel - vadd.cpp
1. 代码结构
代码结构:load / compute / store
2. 关键词解释
- load / store:尽可能高效地完成数据在 Kernel 和 Host 之间的流动
- compute:表现为一系列运算函数(compute functions),数据通过 HLS streams 传递,包含一组嵌套的循环。
- HLS steams:
hls::stream
在运算函数之间传递数据,具有阻塞(blocking)逻辑的特征,可以在函数之间同步变量值 - Dataflow pragma:指示 compiler 使能任务级(task-level)流水,是并行、流水执行 load / compute / store 的必要步骤
- vector 数据类型:
hls::vector
,vector 的长度由 I/O 端口的宽度决定。将计算单元的宽度设置成与 I/O 端口的宽度相同可以更高效的使用资源。
3. 代码逐段分析
3.1 参数定义
// vdd.cpp line 61-70
// Includes
#include <hls_vector.h>
#include <hls_stream.h>
#include "assert.h"
#define MEMORY_DWIDTH 512
#define SIZEOF_WORD 4
#define NUM_WORDS ((MEMORY_DWIDTH) / (8 * SIZEOF_WORD))
#define DATA_SIZE 4096
// TRIPCOUNT identifier
const int c_size = DATA_SIZE;
-
可以在
Includes
中看到我们将要使用的两种数据类型hls::stream
和hls::vector
。前者在运算函数之间阻塞地传递数据,后者主要用于 I/O 端口。 -
在计算
NUM_WORDS
时,由于一个 kernel 端口的最大值为 512 bits,因此有NUM_WORDS = 512 bits / (8 bits per byte * 4 byte per word)
-
DATA_SIZE
规定了我们实际需要运算的数据长度,一般远长于 I/O 端口宽度。在本例中,我们待求和的数据是DATA_SIZE
个 int 型数据
// host.cpp line 29
size_t vector_size_bytes = sizeof(int) * DATA_SIZE;
-
最后一句对
tripcount
的设置与 HLS pragma loop_tripcount 的设置有关。语法为#pragma HLS loop_tripcount min=<int> max=<int> avg=<int>
min, max, avg 分别对应循环迭代的最小、最大和平均次数。
从