Vitis HLS 学习笔记--基本指针和算术指针

目录

1. 简介

2. 基本指针

3. 算术指针

4. 疑点解答

4.1 疑点1

4.2 疑点2

5. 总结


1. 简介

在 C/C++ 语言中,指针被广泛用来表示内存中的地址信息,它们是理解和使用这些语言的核心概念之一。然而,在 Vitis HLS 中,指针的使用有着显著的差异。尽管 Vitis HLS 支持指针的综合,但在某些情况下,使用指针可能会导致综合后的 RTL 接口与设计时的预期不符,尤其是在以下情况下:

  • 在同一函数内多次访问(读取或写入)指针时。
  • 使用指针数组时,每个指针都必须指向一个标量或标量数组(而不是另一个指针)。
  • 仅支持标准 C/C++ 语言类型间的指针强制转换。

虽然 Vitis HLS 支持指针的使用,但通常建议避免在代码中使用指针,尤其是在需要高效硬件实现的情况下。

在顶层函数的接口上使用指针时,应该特别注意指针的实现方式,以确保综合结果符合设计要求。在某些情况下,可能需要通过修改代码或选择不同的接口类型来解决由指针使用引起的问题。

2. 基本指针

基本指针,指的是直接指向数据的指针,而不需要复杂的指针操作,如指针数组或指针算术。

在 Vitis HLS 中,如果一个函数的顶层接口使用了基本指针,这通常不会对硬件综合产生负面影响。

用一个简单的比喻来理解这个概念:

你有一栋大楼(这里指的是你的硬件设计),而指针就像是大楼里的电梯。基本指针就像是一个直达特定楼层的电梯,它可以直接带你到达你想去的地方(即直接访问数据)。在 Vitis HLS 中,这样的电梯(基本指针)是可以被很好地管理和综合,因为它们的行为很直接,很容易预测。

现在,有两种方式可以让这些电梯(指针)工作:

  • 有线接口:这就像是一个普通的电梯,它在你按下按钮时就开始工作。在硬件中,有线接口意味着数据可以直接从一个地方传输到另一个地方,没有复杂的控制逻辑。
  • 握手接口协议:这更像是一个智能电梯,它会在确认你准备好了之后才开始运行。在硬件中,握手接口会在收到一个特定的信号(ready)后才开始数据传输。这种方式允许更精细的控制数据流,但也更复杂一些。

只要你的指针像一个直达电梯那样简单直接,Vitis HLS 就能够很好地处理它,无论是通过有线接口还是握手接口协议。这样的指针不会给硬件综合带来问题,因为它们的行为很容易在硬件中实现。

void example(int *d) {
  static int acc = 0;

  acc += *d;
  *d = acc;
}

测试代码:

#include <stdio.h>
extern void example(int *d);

int main() {
  int d;
  int i;

  printf(" Din Dout\n");

  // Create input data
  // Call the function to operate on the data
  for (i = 0; i < 4; i++) {
    d = i;
    example(&d);
    printf("  %d   %d\n", i, d);
  }

  // Return 0 if the test passed
  return 0;
}

 输出的结果:

Call   Din  Dout
1st     0    0
2nd     1    1
3rd     2    3
4th     3    6

查看综合报告 HW Interfaces 部分:

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

 可以看到,指针d是通过 ap_none 接口实现的。 

3. 算术指针

在 Vitis HLS 中,指针算术的使用与传统的连线、握手或 FIFO 接口的数据访问方式存在显著差异。

算术指针允许开发者进行无序访问,即可以直接通过地址运算来访问任意位置的数据,如下代码:

void example(int *d) {
  static int acc = 0;
  int i;

  for (i = 0; i < 4; i++) {
    acc += *(d + i + 1);
    *(d + i) = acc;
  }
}

在这段代码中,指针 d 被用来访问和修改数组中的元素,且访问顺序不是连续的。

对应生成的IP:

对应的测试代码: 

#include <stdio.h>
extern void example(int *d);

int main() {
  int d[5], ref[5];
  int i;

  // Create input data
  for (i = 0; i < 5; i++) {
    d[i] = i;
    ref[i] = i;
  }

  // Call the function to operate on the data
  example(d);

  printf(" Din Dout\n");
  for (i = 0; i < 4; i++) {
    printf("  %d   %d\n", ref[i], d[i]);
  }

  return 0;
}

如果直接运行 C Simulation,那么仿真是通过的。

这种方式在软件编程中非常灵活,但在硬件设计中可能会引入问题。

相比之下,连线、握手或 FIFO 接口则要求数据必须按照固定的顺序进行访问。这意味着数据的读取和写入操作必须从数组的第一个元素开始,然后依次进行。这种顺序性要求与算术指针的灵活性相冲突。

  • 连线接口:当数据准备就绪时,接口会读取数据。这种方式适合于数据流的连续处理。
  • 握手和 FIFO 接口:当控制信号允许时,接口会执行读写操作。这种方式适合于需要同步控制的场景。

由于 Vitis HLS 不支持对连线、握手或 FIFO 接口建立数据索引,因此在硬件实现中,如果使用了算术指针,就需要某种形式的数据索引机制。为了解决这个问题,可以将指针替换为数组,并通过 RAM (ap_memory) 接口来实现代码,如下所示:

void example(int d[5]) {
  static int acc = 0;
  int i;

  for (i=0; i<4; i++) {
    acc += d[i+1];
    d[i] = acc;
  }
}

查看综合报告 HW Interfaces 部分:

================================================================
== HW Interfaces
================================================================
* AP_MEMORY
+------------+----------+
| Interface  | Bitwidth |
+------------+----------+
| d_address0 | 3        |
| d_address1 | 3        |
| d_d0       | 32       |
| d_q1       | 32       |
+------------+----------+

可以看到,数组d已经通过 ap_memory 接口来实现了。 

4. 疑点解答

4.1 疑点1

基本指针代码输出的IP如下,这个模块是在每个周期执行一次吗?

答:不是。执行状态受块级控制协议 ap_hs 控制,在使能期间,每个周期可以执行一次。对应到仿真程序上,调用 example(&d) 则执行一次。

4.2 疑点2

void example(int d[5]) {
  static int acc = 0;
  int i;

  for (i=0; i<4; i++) {
    acc += d[i+1];
    d[i] = acc;
  }
}

对应的IP如下,通过块级控制协议启动一次,就能实现对存储器中4个元素进行操作吗?

答:是的。启动该IP后, HLS core 会自动操作存储器4次,完成数据的读写,完毕后,使能 ap_done信号。

5. 总结

在Vitis HLS中,指针的使用与传统的C/C++环境存在显著差异,尤其是在涉及硬件综合时。基本指针可以直接指向数据,并且通常不会对硬件综合产生负面影响,但在顶层函数的接口中使用时需要注意指针的实现方式。另一方面,算术指针的灵活性在软件编程中很有用,但在硬件设计中可能引入问题,因为硬件需要按照固定顺序访问数据。为了克服这些问题,可以通过使用数组和RAM接口来替代指针,以更好地满足硬件设计的需求。总之,在进行Vitis HLS设计时,需要仔细考虑指针的使用方式,以确保最终的硬件实现符合设计要求。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/633727.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

ChatGPT、Llama等大模型回答脑筋急转弯

分别使用ChatGPT3.5、 4.0 和Llama 2 70B 和3 70B这四个应用最广的大模型来回答这个流传最广的脑筋急转弯。 树上10知鸟&#xff0c;打死2只&#xff0c;还有几只&#xff1f; 看看它们的表现吧&#xff1a; 题目树上10知鸟&#xff0c;打死2只&#xff0c;还有几只&#xf…

保护共享资源的方法(互斥锁)

我最近开了几个专栏&#xff0c;诚信互三&#xff01; > |||《算法专栏》&#xff1a;&#xff1a;刷题教程来自网站《代码随想录》。||| > |||《C专栏》&#xff1a;&#xff1a;记录我学习C的经历&#xff0c;看完你一定会有收获。||| > |||《Linux专栏》&#xff1…

【BSP开发经验】简易文件系统digicapfs实现方式

文章目录 背景Linux vfs框架介绍数据结构系统调用openwriteread 总体框架 Linux 磁盘高速缓存机制标准文件访问同步文件访问异步文件访问buffer_head 如何实现一个简单的文件系统blkdevfs注册文件系统产生一个文件让文件变得可读可写 背景 在新的分区升级启动方案中需要分别实…

快手二面准备【面试准备】

快手二面准备【面试准备】 前言版权快手二面准备秋招一面中的问题实习一面中的问题计算机网络和操作系统论坛项目登录注册ThreadLocal代替session存储用户秒杀项目登录注册->阿里验证码->rpcsession为什么改为token实现&#xff0c;redis存储用户信息由binlog的用法->…

【Unity】免费的高亮插件——QuickOutline

除了常见的HighLightSystem来实现的高亮功能&#xff0c;其实还有很多的方法实现物体的高亮。 在 Unity资源商店 搜索OutLine&#xff0c;就会有很多免费好用的高亮插件。 下面介绍一下 QuickOutline这个插件&#xff0c;在 Unity资源商店 搜索到后&#xff0c;点击进去就可以…

网络模型-Qinq配置与应用

Qinq配置与应用 通过配置Qinq来实现利用公网提供的VLAN100使企业1互通&#xff0c;利用公网提供的VLAN200使企业2互通不同企业之间互相隔离。并通过在连接其它厂商设备的接口上配置修改0in0外层VLAN Tag的TPID值&#xff0c;来实现与其它厂商设备的互通。 一、创建VLAN #在Swi…

薪资不公、晋升无望?动笔写一份申诉材料吧!

薪资不公、晋升无望&#xff1f;动笔写一份申诉材料吧&#xff01; 引言&#xff1a;每个努力工作的人都值得公平对待 在职场上&#xff0c;我们付出了汗水和智慧&#xff0c;期待着相应的回报——合理的工资和公正的晋升机会。然而&#xff0c;现实并不总是如此美好。当你感觉…

Thingsboard规则链:Entity Type Filter节点详解

在物联网&#xff08;IoT&#xff09;的世界里&#xff0c;数据的多样性与复杂性要求处理架构具备高度的灵活性和针对性。ThingsBoard作为一款强大的物联网平台&#xff0c;通过其规则链&#xff08;Rule Chains&#xff09;机制&#xff0c;让数据的自动化处理变得既强大又灵活…

谓词逻辑(一)

一、句子的谓词符号化 谓词逻辑&#xff0c;也叫一阶逻辑&#xff0c;它对每个最简单的命题尽一步进行分解。 1个体词&#xff1a;可以独立存在的客体。 2谓词&#xff1a;描述一个个体词的属性或多个个体词之间的关系&#xff08;可用一元函数和多元函数来理解&#xff09;…

18.SpringCloud Gateway

简介 SpringCloud Gateway是spingcloud家族的产品&#xff0c;使用netty实现的高性能服务网关&#xff0c;用于替换netflix公司的zuul网关实现。 参考地址&#xff1a; https://spring.io/projects/spring-cloud 术语 工作原理 Route Predicate Factories GatewayFilte…

降本增效!看TeeChart如何帮助实现海量「监测数据」可视化

“环境监测数据异常庞大&#xff0c;想要实现数据监测分析&#xff0c;除了要求控件具有良好的兼容性和稳定性&#xff0c;还对多样化、定制化的图表开发也有很高的要求” ——————— 项目负责工程师 王工 TeeChart Pro 最新版下载&#xff08;qun&#xff1a;740060302&…

C++初阶学习第十弹——探索STL奥秘(五)——深入讲解vector的迭代器失效问题

vector&#xff08;上&#xff09;&#xff1a;C初阶学习第八弹——探索STL奥秘&#xff08;三&#xff09;——深入刨析vector的使用-CSDN博客 vector&#xff08;中&#xff09;&#xff1a;C初阶学习第九弹——探索STL奥秘&#xff08;四&#xff09;——vector的深层挖掘和…

JVM学习-堆空间(一)

堆空间 每个进程&#xff08;JVM实例&#xff09;拥有唯一的方法区和堆空间&#xff0c;拥有唯一的Runtime实例(基于饿汉式方式)&#xff0c;线程共享进程的方法区和堆空间&#xff0c;每个线程拥有独立的程序计数器、本地方法栈和虚拟机栈。 一个JVM实例只存在一个堆内存&am…

windows docker desktop 更换镜像存储目录

windows docker desktop 更换镜像存储目录 方法&#xff1a;如图&#xff0c;Browse浏览一个新的目录并选中&#xff0c;确定后&#xff0c;程序会开始stop&#xff0c;在stop完成前&#xff0c;会持续迁移原有镜像到新的位置&#xff0c;你会发现目标位置的磁盘占用空间越来越…

内网穿透--Ngrok-入门-上线

免责声明:本文仅做技术交流与学习... 目录 Ngrok: 技术实现: 前提: 命令: 详细流程及图解: 平台Ngrok: Sunny-Ngrok内网转发内网穿透 - 国内内网映射服务器 支持的协议&#xff1a;tcp、http、https 支持的类型&#xff1a;正向代理、反向代理 --隧道开通免费的 --协议…

论文降重攻略!复盘降重至5.7%,aigc降到0%的经验!

论文降重攻略&#xff01;复盘降重至5.7%,aigc降到0%的经验&#xff01; 首先要提一个敲好用的论文降重软件-蝌蚪论文&#xff0c;当知网查重46%的时候有没有和我一样头都要炸的感觉&#xff0c;最关键的是自己改了几天还是没降下去。 索性删了好多标红的&#xff0c;但查重率…

别说废话!说话说到点上,项目高效沟通的底层逻辑揭秘

假设你下周要在领导和同事面前汇报项目进度&#xff0c;你会怎么做&#xff1f;很多人可能会去网上搜一个项目介绍模板&#xff0c;然后按照模板来填充内容。最后&#xff0c;汇报幻灯片做了 80 页&#xff0c;自己觉得非常充实&#xff0c;但是却被领导痛批了一顿。 这样的境…

四天学会JS高阶(学好vue的关键)——深入面向对象(理论+实战)(第三天)

***本章面试使用居多* 理论篇**一、编程思想 1.1 面向过程 JS 前端居多 按照步骤 性能高 适合跟硬件关系很紧密 没有面向对象易维护易复用易扩展 1.2 面向对象 java典型 按照功能&#xff0c;把事务分别成一个个对象&#xff0c;对象之间分工合作 比较灵活 适合多人合作的…

Java基础(三)- 多线程、网络通信、单元测试、反射、注解、动态代理

多线程基础 线程&#xff1a;一个程序内部的一条执行流程&#xff0c;只有一条执行流程就是单线程 java.lang.Thread代表线程 主线程退出&#xff0c;子线程存在&#xff0c;进程不会退出 可以使用jconsole查看 创建线程 有多个方法可以创建线程 继承Thread类 优点&#x…

MPLS VPN

不是公司的产品&#xff0c;是运营商对外提供的一种服务 没咋懂&#xff0c;oh my god