课时3:Vitis HLS设计流程(实例演示)——Vitis HLS教程


1. 前言

课时2我们介绍了Vitis HLS的设计流程,如下图所示:
在这里插入图片描述

算法或软件的设计和仿真都基于C/C++,通过HLS平台导出打包好的IP RTL代码,最后将该打包的IP加入到主工程使用。

本课时,我们通过一个具体的实例,演示HLS设计流程。

2. Vitis HLS设计注意事项

  • 在Vitis HLS中,只有一个函数可以设为顶层综合函数,但不能是main()函数。

  • 任何在顶层函数下的子函数都会被综合,并且综合后得到代码的函数层级结构可以保留。
    在这里插入图片描述

  • 有些代码和结构是不可被Vitis HLS综合的,包括动态分配存储空间、与操作系统相关操作等。

3. Vitis HLS设计示例

3.1 Vitis HLS工程建立

(1)新建Vitis HLS工程,如下图所示,工程名为“HLS_StartDemo”;
在这里插入图片描述

(2)指定要综合的顶层函数名称,此处我们填写待综合的函数名称为“VectorAdd”;
在这里插入图片描述

(3)可以在建立工程的时候,暂时不添加Testbench文件。
在这里插入图片描述

(4)创建Solution,同时要指定Solution名称,模块的时钟周期以及FPGA器件型号。
在这里插入图片描述

(5)添加示例代码,示例工程代码主要包含3个文件:
在这里插入图片描述

其中,VectorAdd.h 为头文件;VectorAdd.cpp为源文件;VectorAdd_tb.cpp为Test Bench。该工程代码主要实现的功能是:在一个for循环内,对一个数组做加法。顶层函数如下:
在这里插入图片描述

测试的Testbench部分截图如下:
在这里插入图片描述

Testbench里既包含了测试数据,也包含了正确的输出结果用于做仿真比较。
工程文件加完后,工程结构如下图所示:
在这里插入图片描述

3.2 仿真和综合

(1)对工程进行仿真,在菜单栏中点击“C Simulation”。
在这里插入图片描述

得到的仿真输出如下,可以看到结果显示“Test Pass”。
在这里插入图片描述

(2)仿真通过后,对工程进行综合,在菜单栏中点击“C Synthesis”。
在这里插入图片描述

打开综合报告,可以看到C代码被综合成RTL代码后,使用的硬件资源评估、性能评估等等。
在这里插入图片描述
在这里插入图片描述

(3)综合通过后,对工程进行联合仿真,在菜单栏中点击“Co-Simulation”。
在这里插入图片描述
在这里插入图片描述

可以查看到联合仿真后的仿真报告。报告显示了联合仿真的状态为“Pass”,并附有一些性能评估报告。
在这里插入图片描述

(4)联合仿真通过后,我们可以打开波形查看窗口“Open Wave Viewer…”
在这里插入图片描述

更加直观的查看仿真结果是什么样子,查看结果时会自动打开Vivadao。
在这里插入图片描述

其中“Block-level IO Handshake”端口为握手端口信号:
在这里插入图片描述

以下为输入输出数组或变量端口,端口包含地址总线、使能信号、写使能信号、数据总线等:
在这里插入图片描述

3.3 创建另一个Solution

(1)创建新Solution
Vitis HLS给用户提供了非常方便创建新Solution的接口。用户可以点击工具栏上的“New Solution”来给同样的工程代码创建新的Solution。
在这里插入图片描述

新的Solution命名为“solution2”,同时我们勾选“Copy directives and constraints from solution: solution1”选项,即solution2拷贝了solution1原有的directives指令(该示例中,solution1的directives指令为空)。
在这里插入图片描述

(2)给命名为“myloop”的循环添加directive指令。右键“myloop”,点击“Insert Directive…”
在这里插入图片描述

我们选择了“HLS PIPELINE”指令(这些指令的含义将在后面课时着重讲解);
在这里插入图片描述

(3)针对“solution2”对工程进行综合,生成综合报告。
(4)在菜单栏中点击“Compare Reports…”,比较同样的工程在两个Solutions下综合出来的结果。
在这里插入图片描述

(5)由于在Vitis HLS 2021.1版本中,建立新工程(solution1)时即便没有添加directives,HLS会给solution默认添加“HLS PIPELINE”指令。而我们给solution2添加的directives也为“HLS PIPELINE”指令,因此两个Solutions综合编译出来的结果是一致的(大家可以尝试添加不同的directives指令,然后对比下不同Solutions综合编译出的结果)。
在这里插入图片描述

4. 总结

  • 在写C代码的时候,对于每个for循环,最好都创建一个标签(如该例程中的“myloop”标签)。这样有利于后期对每个循环添加不同的directives;
  • main()函数的返回值,在没有错误的时候,返回值设为0,有错误的时候,返回值设为1,这样有利于判断仿真是否出错;

最后用一张图总结下该C例程代码使用HLS综合后,生成的接口结构。
在这里插入图片描述


参考文献:
[1]《Vitis High-Level Synthesis User Guide》. UG1399. Xilinx
[2] “跟Xilinx SAE学HLS系列视频讲座-高亚军 ”https://www.bilibili.com/video/av41246874

如果大家对我们的文章感兴趣,可以关注我们的公众号:“FpgaHome”,实时关注我们的更新动态。
该工程对应的源码可以通过关注该微信公众号,在公众号输入“HLS_DEMO”来获取工程的下载链接,工程采用的是Vitis HLS 2021.1版本。

  • 8
    点赞
  • 60
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
以下是一个简单的 Vitis HLS 设计案例: 假设我们有一个输入为整数数组和一个常数值的函数,需要将数组中的每个元素与该常数值相加并返回新的数组。我们可以使用 Vitis HLS 设计这个函数。 第一步:定义输入和输出 我们需要定义输入和输出的数据类型和大小。在这个案例中,我们定义输入为一个大小为 10 的整数数组和一个常数值,输出为一个大小为 10 的整数数组。因此,我们可以使用以下代码定义输入和输出: ```c++ #define N 10 typedef int in_data_t; typedef int out_data_t; void array_add(in_data_t input[N], in_data_t constant, out_data_t output[N]) { ... } ``` 第二步:编写算法 我们需要编写一个算法,将输入数组中的每个元素与常数值相加,并将结果存储在输出数组中。这可以使用一个简单的 for 循环完成,如下所示: ```c++ void array_add(in_data_t input[N], in_data_t constant, out_data_t output[N]) { for (int i = 0; i < N; i++) { output[i] = input[i] + constant; } } ``` 第三步:进行 Vitis HLS 优化 在进行 Vitis HLS 优化之前,我们需要将输入和输出数据类型转换为 ap_int 和 ap_fixed 类型,以便在 FPGA 上进行计算。我们还需要添加一些 HLS 指令来告诉编译器如何优化代码。 ```c++ #include "ap_int.h" #include "ap_fixed.h" #define N 10 typedef ap_int<32> in_data_t; typedef ap_int<32> out_data_t; #pragma HLS INTERFACE s_axilite port=return bundle=control #pragma HLS INTERFACE s_axilite port=input bundle=control #pragma HLS INTERFACE s_axilite port=constant bundle=control #pragma HLS INTERFACE s_axilite port=output bundle=control void array_add(in_data_t input[N], in_data_t constant, out_data_t output[N]) { #pragma HLS PIPELINE II=1 #pragma HLS INTERFACE axis port=input #pragma HLS INTERFACE axis port=output for (int i = 0; i < N; i++) { #pragma HLS UNROLL output[i] = input[i] + constant; } } ``` 在这个例子中,我们使用了以下 HLS 指令: - `#pragma HLS PIPELINE II=1`:指定流水线间隔为 1,以最大化吞吐量。 - `#pragma HLS INTERFACE axis port=input` 和 `#pragma HLS INTERFACE axis port=output`:指定输入和输出流的类型为 AXIS,这是一种常用的数据接口。 - `#pragma HLS UNROLL`:指定循环展开,以最大化吞吐量。 第四步:编译和验证 最后,我们需要使用 Vivado HLS 编译代码,并在 FPGA 上验证结果是否与预期相符。这可以通过 Vivado 开发环境中的仿真和合成工具完成。如果一切正常,我们可以将生成的 IP 核组成一个 Vivado 设计,并将其部署到 FPGA 上以实现加速。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值