Vitis HLS 学习笔记--避免使用多重访问指针

目录

1. 简介

2. 代码解析

2.1 pointer_stream_bad

2.2 pointer_stream_better

2.3 pointer_stream_good

3. 总结


1. 简介

本文将探讨在 Vitis HLS 中正确处理多重访问指针重要性以及其对功能的影响。通过分析示例代码,我们将讨论在如何正确处理指针访问,以及如何避免由于指针多次访问而导致的问题。从错误示例到更好的解决方案,我们将探讨使用 volatile 限定符、串流数据类型以及显式访问指针元素等方法来确保 RTL 设计的正确性。

2. 代码解析

2.1 pointer_stream_bad

在这个错误示例中,指针 d_i 被读取了 4 次,而指针 d_o 则被写入了 2 次,导致指针多次被访问

void pointer_stream_bad ( dout_t *d_o, din_t *d_i) {
din_t acc = 0;
acc += *d_i;
acc += *d_i;
*d_o = acc;
acc += *d_i;
acc += *d_i;
*d_o = acc;
}

然而,在综合后的 RTL 设计中,该代码只会读取 1 次输入端口并写入 1 次输出端口。

原因:与标准 C/C++ 编译器一样,Vitis HLS 会优化掉多余的指针访问

2.2 pointer_stream_better

要实现上述代码的功能,即对 d_i 读取 4 次,对 d_o 写入 2 次,必须将指针指定为 volatile:

void pointer_stream_better(volatile int *d_o, volatile int *d_i) {
#pragma HLS INTERFACE mode=ap_hs port=d_o //通过ap_hs接口
#pragma HLS INTERFACE mode=ap_hs port=d_i //通过ap_hs接口

// #pragma HLS INTERFACE mode=ap_fifo depth=2 port=d_o //通过ap_fifo接口
// #pragma HLS INTERFACE mode=ap_fifo depth=4 port=d_i //通过ap_fifo接口

  int acc = 0;

  acc += *d_i;
  acc += *d_i;
  *d_o = acc;
  acc += *d_i;
  acc += *d_i;
  *d_o = acc;
}

volatile 限定符作用:

  • 阻止指针访问最优化
  • 生成的 RTL 设计执行流程如同 “C语言” 一样,会按照周期进行,对输入端口 d_i 执行 4 次读取,对输出端口 d_o 执行 2 次写入。

输入指针 d_i 和输出指针 d_o 在 RTL 中是作为 hs(或 fifo)接口实现的,目的是为了确保:

  • 每次在 RTL 端口 d_i 上执行读取时,上游生产者模块都可提供新数据。
  • 每次写入 RTL 端口 d_o 时,下游使用者模块都接受新数据。 

可以通过查看综合报告加以确认:

================================================================
== HW Interfaces
================================================================
* REGISTER
+-----------+-------+----------+
| Interface | Mode  | Bitwidth |
+-----------+-------+----------+
| d_i       | ap_hs | 32       |
| d_o       | ap_hs | 32       |
+-----------+-------+----------+

* SW-to-HW Mapping
+----------+--------------+---------+
| Argument | HW Interface | HW Type |
+----------+--------------+---------+
| d_o      | d_o          | port    |
| d_o      | d_o_ap_vld   | port    |
| d_o      | d_o_ap_ack   | port    |
| d_i      | d_i          | port    |
| d_i      | d_i_ap_vld   | port    |
| d_i      | d_i_ap_ack   | port    |
+----------+--------------+---------+

上述报告是按照 ap_hs 接口进行综合的,可以看到输出 IP 包含了相应的硬件接口。 

2.3 pointer_stream_good

不同于软件,硬件系统的并发性质使其能够充分利用串流数据。数据可持续不断提供给 HLS IP,HLS IP 可持续不断输出数据。HLS IP 可在完成处理现有数据之前接受新数据。

有多种方法可以优化上述代码:

  • 添加 volatile 限定符,测试激励文件不会对专用读写进行建模,使用原 C/C++ 语言测试激励文件的 RTL 仿真可能失败,但通过查看追踪文件波形可以发现执行的读写操作正确。
  • 修改代码以对显式专用读写进行建模。请参阅以下示例。
  • 修改代码以使用串流数据类型。串流数据类型支持对使用串流数据的硬件进行准确建模。
void pointer_stream_better(volatile int *d_o, volatile int *d_i) {
 #pragma HLS INTERFACE mode=ap_fifo depth=2 port=d_o
 #pragma HLS INTERFACE mode=ap_fifo depth=4 port=d_i

  int acc = 0;

  acc += *d_i;
  acc += *(d_i + 1);
  *d_o = acc;
  acc += *(d_i + 2);
  acc += *(d_i + 3);
  *(d_o + 1) = acc;
}

以上代码,通过数组(指针)索引的方式显式地访问指针 d_i 和 d_o 的每个元素。由于指针访问按顺序进行并从位置 0 开始,因此综合期间可使用串流接口类型。

3. 总结

虽然 Vitis HLS 在指针上支持多重访问指针,但强烈建议使用 hls::stream 类替代多重访问指针来实现所需的行为,以避免陷入困难。如果设计使用接口上的顶层函数的实参列表中的指针,那么在使用指针执行多重访问时需考量一些特殊注意事项。当任一指针以相同方式多次执行读取或写入时,就会发生多重访问。

  • 10
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值