Vitis HLS 学习笔记--优化指令-BIND_OP_STORAGE

目录

1. BIND_OP_STORAGE 概述

1.1 BIND_OP

1.2 BIND_STORAGE

2. 语法解析

2.1 BIND_OP

2.2 BIND_OP 用法示例

2.3 BIND_STORAGE

2.4 BIND_STORAGE 示例

3. 实例演示

4. 总结


1. BIND_OP_STORAGE 概述

BIND_OP_STORAGE 其实是两个优化指令的合称:BIND_OP 和 BIND_STORAGE。

1.1 BIND_OP

Vitis HLS 使用特定 impl 来实现代码中的运算。BIND_OP 编译指示用于指定针对每个特定变量,都应将一项运算(mul、add、div)映射到特定器件资源,以便在 RTL 内实现 (impl)。如果不指定 BIND_OP 编译指示,Vitis HLS 会自动判定用于运算的资源。

1.2 BIND_STORAGE

BIND_STORAGE 编译指示用于将代码中的变量(阵列或函数实参)分配给 RTL 中的特定存储器类型 (type)。如果不指定此编译指示,那么 Vitis HLS 工具会判定要分配的存储器类型。HLS 工具在硬件中使用指定的实现 (impl) 来实现该存储器。

2. 语法解析

2.1 BIND_OP

#pragma HLS bind_op variable=<variable> op=<type> impl=<value> latency=<int>
  • variable=<variable>:用于定义要将 BIND_OP 编译指示分配到的变量
  • op=<type>:用于定义要绑定到特定实现资源的运算。受支持的函数运算包括:mul、add 和 sub 受支持的浮点运算包括:fadd、fsub、fdiv、fexp、flog、fmul、frsqrt、frecip、fsqrt、dadd、dsub、ddiv、dexp、dlog、dmul、drsqrt、drecip、dsqrt、hadd、hsub、hdiv、hmul 和 hsqrt。
  • impl=<value>:定义用于指定运算的实现。受支持的函数运算实现包括 fabric 和 dsp。受支持的浮点运算实现包括:fabric、meddsp、fulldsp、maxdsp 和 primitivedsp。
  • latency=<int>:定义运算的实现的默认时延。有效的时延值因指定的 op 和 impl 而异。默认值为 -1,即交由 Vitis HLS 选择时延。

支持的整数运算操作:

OP

Impl

Min Latency

Max Latency

add

fabric

0

4

add

dsp

0

4

mul

fabric

0

4

mul

dsp

0

4

sub

fabric

0

4

sub

dsp

0

0

 支持的浮点数运算操作:

操作

实现

Min Latency

Max Latency

fadd

fabric

0

13

fadd

fulldsp

0

12

fadd

primitivedsp

0

3

fexp

meddsp

0

21

fmul

maxdsp

0

7

快速记忆方法:

受支持的函数运算包括:
mul、add 、 sub受支持的浮点运算包括:
fadd fsub fdiv fexp flog fmul frsqrt frecip fsqrt
dadd dsub ddiv dexp dlog dmul drsqrt drecip dsqrt
hadd hsub hdiv           hmul               hsqrt

Impl解释:

  • fabric: 使用 FPGA 的逻辑单元和 RAM 块来实现算法。
  • dsp: 使用 FPGA DSP 功能来实现算法,例如 FFTFIRDDS 等。
  • meddsp: 使用 FPGA DSP 功能和一些逻辑单元来实现算法,适合中等复杂度的算法。
  • maxdsp: 使用 FPGA DSP 功能和更多的逻辑单元来实现算法,适合高复杂度的算法。
  • fulldsp: 使用 FPGA 的所有可用资源来实现算法,包括 DSPRAM 和逻辑单元。

2.2 BIND_OP 用法示例

double mult (double a, double b) {double c, d;
#pragma HLS BIND_OP variable=c op=dmul impl=fabric  latency=2
#pragma HLS BIND_OP variable=d op=dmul impl=fulldsp latency=10c = a * b;d = a * c;return d;
}

解释: 

  • 指定变量 的双精度浮点运算,实现方式fabric,延时为2
  • 指定变量 的双精度浮点运算,实现方式为fulldsp,延时为10

Vitis HLS 编译器得到的结果如下:

从命名可以看出:

  • dmul: 双精度乘法器。
  • 64ns: 输入数据的位宽是 64 位,ns的含义不明
  • 64: 输出数据的位宽是 64 位,3和5的含义不明。
  • max_dsp: 实现方法是使用最大数量的 DSP 功能。
  • U2: 模块的实例名字。

注意:

  • 编译器对待手动指定latency,会优先满足时钟频率上的要求,然后尽量靠近用户指定的latency
  • 如上述案例,虽然指定了latency=2,但是编译器需要latency等于3才能满足时钟频率要求。
  • 给定更多latency,系统能运行在更高的时钟频率上。

2.3 BIND_STORAGE

#pragma HLS bind_storage variable=<variable> type=<type> [ impl=<value> latency=<int> ]
  • variable=<variable>:定义要将 BIND_STORAGE 编译指示分配到的变量。
  • type=<type>:定义要绑定到指定变量的存储器的类型。受支持的类型包括:fifo、ram_1p、ram_1wnr、ram_2p、ram_s2p、ram_t2p、rom_1p、rom_2p、rom_np。
  • impl=<value>:定义指定存储器类型的实现。受支持的实现包括:bram、bram_ecc、lutram、uram、uram_ecc、srl、memory 和 auto,如下所述。
  • latency=<int>:定义用于绑定类型的默认时延。如下表所示,有效的时延值因指定的 type 和 impl 而异。默认值为 -1,即交由 Vitis HLS 选择时延。

存储类型:

类型

描述

FIFO

FIFOVitis HLS 可判定如何在 RTL 中将其实现,除非指定 -impl 选项。

RAM_1WNR

1 个写入端口和 N 个读取端口的 RAM,内部使用 N bank

RAM_2P

双端口 RAM,允许在某一端口上执行操作,并在另一个端口上执行读写操作。

RAM_S2P

双端口 RAM,允许在某一端口上执行操作,并在另一个端口上执行操作。

RAM_T2P

真正的双端口 RAM,支持在 2 个端口上执行读写操作。

ROM_1P

单端口 ROMVitis HLS 可判定如何在 RTL 中将其实现,除非指定 -impl 选项。

ROM_2P

双端口 ROM

ROM_NP

多端口 ROM

实现类型:

名称

描述

MEMORY

通用存储器,允许 Vivado 工具选择实现。

URAM

UltraRAM 资源

URAM_ECC

ECC UltraRAM

SRL

移位寄存器逻辑资源,Shift Register Look-up Table(移位寄存器查找表)

LUTRAM

分布式 RAM 资源

BRAM

RAM 资源

BRAM_ECC

ECC 的块 RAM

AUTO

Vitis HLS 会自动判定变量的实现。

受支持的存储器类型、实现和时延组合:

操作

实现

Min Latency

Max Latency

FIFO

BRAM

0

0

FIFO

LUTRAM

0

0

FIFO

MEMORY

0

0

FIFO

SRL

0

0

FIFO

URAM

0

0

RAM_1P

AUTO

1

3

RAM_1P

BRAM

1

3

RAM_1P

LUTRAM

1

3

RAM_1P

URAM

1

3

RAM_1WNR

AUTO

1

3

RAM_1WNR

BRAM

1

3

RAM_1WNR

LUTRAM

1

3

RAM_1WNR

URAM

1

3

RAM_2P

AUTO

1

3

RAM_2P

BRAM

1

3

RAM_2P

LUTRAM

1

3

RAM_2P

URAM

1

3

操作

实现

Min Latency

Max Latency

RAM_S2P

BRAM

1

3

RAM_S2P

BRAM_ECC

1

3

RAM_S2P

LUTRAM

1

3

RAM_S2P

URAM

1

3

RAM_S2P

URAM_ECC

1

3

RAM_T2P

BRAM

1

3

RAM_T2P

URAM

1

3

ROM_1P

AUTO

1

3

ROM_1P

BRAM

1

3

ROM_1P

LUTRAM

1

3

ROM_2P

AUTO

1

3

ROM_2P

BRAM

1

3

ROM_2P

LUTRAM

1

3

ROM_NP

BRAM

1

3

ROM_NP

LUTRAM

1

3

2.4 BIND_STORAGE 示例

#pragma HLS bind_storage variable=coeffs type=RAM_1P impl=bram

解释:

指令告诉HLS工具将 coeffs 数组绑定到一个单端口RAM上,并且使用块RAM作为其实现方式。

3. 实例演示

#define BUFFER_SIZE 1024
#define DATA_SIZE 4096// TRIPCOUNT identifier
const unsigned int c_len = DATA_SIZE / BUFFER_SIZE;
const unsigned int c_size = BUFFER_SIZE;extern "C" {
void vadd(const unsigned int* in1, // Read-Only Vector 1const unsigned int* in2, // Read-Only Vector 2unsigned int* out_r,     // Output Resultint size                 // Size in integer) {unsigned int v1_buffer[BUFFER_SIZE];   // Local memory to store vector1unsigned int v2_buffer[BUFFER_SIZE];   // Local memory to store vector2unsigned int vout_buffer[BUFFER_SIZE]; // Local Memory to store result// Using the BIND_OP pragma the user can specify the operator, implementation
// and latency
#pragma HLS BIND_OP variable = v1_buffer op = mul impl = DSP latency = 2
#pragma HLS BIND_OP variable = v2_buffer op = mul impl = DSP latency = 2
#pragma HLS BIND_OP variable = vout_buffer op = add impl = DSP
// Using the BIND STORAGE the used can choose the type, resource and latency
#pragma HLS BIND_STORAGE variable = v1_buffer type = RAM_1P impl = BRAM latency = 2
#pragma HLS BIND_STORAGE variable = v2_buffer type = RAM_1P impl = LUTRAM latency = 2
#pragma HLS BIND_STORAGE variable = vout_buffer type = RAM_1P impl = URAM// Per iteration of this loop perform BUFFER_SIZE vector additionfor (int i = 0; i < size; i += BUFFER_SIZE) {
#pragma HLS LOOP_TRIPCOUNT min = c_len max = c_lenint chunk_size = BUFFER_SIZE;// boundary checksif ((i + BUFFER_SIZE) > size) chunk_size = size - i;// Auto-pipeline is going to apply pipeline to these loopsread1:for (int j = 0; j < chunk_size; j++) {
#pragma HLS LOOP_TRIPCOUNT min = c_size max = c_sizev1_buffer[j] = in1[i + j] * in1[i + j];}read2:for (int j = 0; j < chunk_size; j++) {
#pragma HLS LOOP_TRIPCOUNT min = c_size max = c_sizev2_buffer[j] = in2[i + j] * in2[i + j];}vadd:for (int j = 0; j < chunk_size; j++) {
// As the outer loop is not a perfect loop
#pragma HLS loop_flatten off
#pragma HLS LOOP_TRIPCOUNT min = c_size max = c_size// perform vector additionvout_buffer[j] = v1_buffer[j] + v2_buffer[j];}// burst write the resultwrite:for (int j = 0; j < chunk_size; j++) {
#pragma HLS LOOP_TRIPCOUNT min = c_size max = c_sizeout_r[i + j] = vout_buffer[j];}}
}
}

其中关键的优化指令如下:

// Using the BIND_OP pragma the user can specify the operator, implementation and latency
#pragma HLS BIND_OP variable = v1_buffer    op = mul impl = DSP latency = 2
#pragma HLS BIND_OP variable = v2_buffer    op = mul impl = DSP latency = 2
#pragma HLS BIND_OP variable = vout_buffer op = add impl = DSP


// Using the BIND STORAGE the used can choose the type, resource and latency
#pragma HLS BIND_STORAGE variable = v1_buffer    type = RAM_1P impl = BRAM     latency = 2
#pragma HLS BIND_STORAGE variable = v2_buffer    type = RAM_1P impl = LUTRAM latency = 2
#pragma HLS BIND_STORAGE variable = vout_buffer type = RAM_1P impl = URAM

运行 Vitis HLS 编译器,我们得到如下结果:

================================================================
== Pragma Report
================================================================
* Valid Pragma Syntax
+----------------+----------------------------------------------------------------+-------------------------+
| Type           | Options                                                        | Location                |
+----------------+----------------------------------------------------------------+-------------------------+
| bind_op        | variable = v1_buffer     op = mul    impl = DSP    latency = 2 | src/vadd.cpp:20 in vadd |
| bind_op        | variable = v2_buffer     op = mul    impl = DSP    latency = 2 | src/vadd.cpp:21 in vadd |
| bind_op        | variable = vout_buffer   op = add    impl = DSP                | src/vadd.cpp:22 in vadd |
| bind_storage   | variable = v1_buffer   type = RAM_1P impl = BRAM   latency = 2 | src/vadd.cpp:24 in vadd |
| bind_storage   | variable = v2_buffer   type = RAM_1P impl = LUTRAM latency = 2 | src/vadd.cpp:25 in vadd |
| bind_storage   | variable = vout_buffer type = RAM_1P impl = URAM               | src/vadd.cpp:26 in vadd |
+----------------+----------------------------------------------------------------+-------------------------+

请注意区分,一个变量可以同时使用这两种绑定,例如 v1_buffer 既被指定了op,又被指定了storage,op 绑定和 storage 绑定关注不同的方面。op 绑定关心的是如何执行计算,而storage 绑定关心的是如何存储数据。

4. 总结

这些指令指导了高级综合(HLS)工具在优化指定数组的存储和操作实现时的行为。它们有助于在 FPGA 设计中实现更好的性能和资源利用率。存储类型的选择(BRAM、LUTRAM 或 URAM)以及专用 DSP 资源的使用会影响设计的整体效率。指定的延迟控制了这些操作的时序特性。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

easyx库的学习(文字绘制)

前言 昨天刚刚写完了基本图形的制作&#xff0c;今天直接可以来看看&#xff0c;在easyx中使用文字 直接看代码吧 文字绘制 void drawTest() {printf("hello,EasyX");//指的是在控制台打印//设置字体大小&#xff0c;样式settextstyle(30, 0, "微软雅黑&quo…

模块三——二分:704.二分查找

文章目录 前言二分查找算法简介特点学习中的侧重点算法原理模板 题目描述算法原理解法一&#xff1a;暴力解法解法二&#xff1a;二分查找算法算法流程细节问题循环结束的条件为什么是正确的&#xff1f;时间复杂度 代码实现 前言 本系列博客是逐渐深入的过程&#xff0c;建议…

BCLinux8U6系统部署oceanbase分布式数据库社区版之一、准备 OBD 中控机

本文记录了在BCLinux8U6操作系统的虚拟服务器准备oceanbase开源数据库的 OBD 中控机的过程。 一、中控机环境 1、虚拟服务器硬件配置 2、操作系统版本信息 [rootlocalhost ~]# cat /etc/os-release NAME"BigCloud Enterprise Linux" VERSION"8.6 (Core)&qu…

【链表】Leetcode 两数相加

题目讲解 2. 两数相加 算法讲解 我们这里设置一个头结点&#xff0c;然后遍历两个链表&#xff0c;使用一个flag记录相加的结果和进位&#xff0c;如果两个链表没有走到最后或者进位不等于0&#xff0c;我们就继续遍历处理进位&#xff1b;如果当前的链表都遍历完成了&#x…

移动Web学习08-响应式布局bootstrap的使用

2、响应式布局 2.1、什么响应式布局 响应式布局是一种网页设计的方法&#xff0c;能够使网站在不同的设备上&#xff08;如桌面电脑、平板电脑、手机等&#xff09;呈现出最佳的用户体验。其核心思想是使网页能够根据用户的设备和屏幕尺寸自动调整布局和内容&#xff0c;以适…

代码随想录算法训练营第五十九天 | 503. 下一个更大元素 II、42. 接雨水

代码随想录算法训练营第五十九天 | 503. 下一个更大元素 II、42. 接雨水 503. 下一个更大元素 II题目解法 42. 接雨水题目解法 感悟 503. 下一个更大元素 II 题目 解法 题解链接 使用两个size class Solution { public:vector<int> nextGreaterElements(vector<in…

【网络原理】UDP协议的报文结构 及 校验和字段的错误检测机制(CRC算法、MD5算法)

目录 UDP协议 UDP协议的报文结构及注意事项 UDP报文结构中的校验和字段 1. 校验和主要校验的内容 2. UDP校验和的实现方式 3. CRC&#xff08;循环冗余校验&#xff09;算法 4. MD5&#xff08;Message Digest Algorithm 5&#xff09; UDP协议 上一篇文章提过&#xf…

计算机网络实验——学习记录五(TCP协议2)

一、TCP协议重传机制 TCP协议是一种面向连接、可靠的传输层协议。为了保证数据的可靠传输&#xff0c;TCP采用数据包重传的机制来应对网络传输过程中可能出现的丢包、错包和乱序等问题。 TCP协议的重传包括超时重传、快速重传、带选择确认SACK的重传和重复SACK重传四种。 二、…

grafana安装篇(1)

目录 grafana概念&#xff1a; 它具有以下主要特点&#xff1a; Grafana 常用于以下场景&#xff1a; 环境介绍&#xff1a; 前置环境&#xff1a; (1)保证可以连接外网 (2)防火墙和selinux已关闭 1.下载安装grafana10.0.1-1rpm包 2.启动grafana 3.浏览器访问 3.设置…

实验2 NFS部署和配置

一、实训目的 1.了解NFS基本概念 2.实现NFS的配置和部署 二、实训准备 1.准备一台能够安装OpenStack的实验用计算机&#xff0c;建议使用VMware虚拟机。 2.该计算机应安装CentOS 7&#xff0c;建议采用CentOS 7.8版本。 3.准备两台虚拟机机&#xff08;客户机和服务器机&…

Linux CPU 占用率 100% 排查

其他层面要考虑到的地方 mysql&#xff0c;有执行时间特别长的sql、死锁redis雪崩等相关问题并发导出数据量大Java定时器服务业务复杂&#xff0c;比如像每天要更新电商的统计表&#xff0c;每天发送优惠券等业务需要提前计算才能保证业务使用时的流畅性&#xff0c;我这个原因…

leetcode最大间距(桶排序+Python)

虽然直接排完序&#xff0c;再求最大差值更快&#xff0c;这里我们还是学一下桶排序。 桶排序主要维护一个bucket&#xff0c;初始bucket【i】 0&#xff0c;遍历nums&#xff0c;当i存在时&#xff0c;令bucket【i】 1&#xff0c;表示存在。遍历完nums&#xff0c;bucket中有…

DiT解读:当Diffusion遇上Transformer

前置知识 ViT Vision Transformer是一种基于Transformer架构的深度学习模型&#xff0c;专门用于处理计算机视觉任务。他的1出现给以往CNN base的图像工作带来了很多新的可能性 ViT的核心思想是将图像分割成均匀的图像块&#xff0c;然后将这些图像块转换为序列&#xff0c;…

【LAMMPS学习】八、基础知识(3.8)计算扩散系数

8. 基础知识 此部分描述了如何使用 LAMMPS 为用户和开发人员执行各种任务。术语表页面还列出了 MD 术语&#xff0c;以及相应 LAMMPS 手册页的链接。 LAMMPS 源代码分发的 examples 目录中包含的示例输入脚本以及示例脚本页面上突出显示的示例输入脚本还展示了如何设置和运行各…

4.点云数据的配准

1.点云配准ICP(Iterative Closest Point)算法 点云配准的原理及ICP(Iterative Closest Point)算法原理参照博客【PCL】—— 点云配准ICP(Iterative Closest Point)算法_icp点云配准-CSDN博客。 &#xff08;1&#xff09;点云配准原理&#xff1a;三维扫描仪设备对目标物体一…

Learn ComputeShader 02 Multiple kernels

前面已经成功创建了第一个compute shader&#xff0c;并且使用它替换掉quad的材质的纹理&#xff0c;现在我们将要在计算着色器中创建多个kernel。 首先调整上次的计算着色器&#xff0c;让它显示为红色。 然后再次创建一个kernel&#xff0c;显示为黄色。 结果应该是这样的…

mysql基础2——字段类型

整数类型 需要考虑存储空间和可靠性的平衡 浮点类型 浮点数类型不精准 将十进制数转换为二进制数存储 浮点数类型&#xff1a;float double real(默认是&#xff0c;double ) 如果需要将real设定为float &#xff0c;那么通过以下语句实现 set sql_mode "real_as…

52 文本预处理【动手学深度学习v2】

将文本作为字符串加载到内存中。 将字符串拆分为词元&#xff08;如单词和字符&#xff09;。 建立一个词表&#xff0c;将拆分的词元映射到数字索引;将文本转换为数字索引序列&#xff0c;方便模型操作。

我在本地部署通义千问Qwen1.5大模型,并实现简单的对话和RAG

节前&#xff0c;我们星球组织了一场算法岗技术&面试讨论会&#xff0c;邀请了一些互联网大厂朋友、参加社招和校招面试的同学&#xff0c;针对算法岗技术趋势、大模型落地项目经验分享、新手如何入门算法岗、该如何准备、面试常考点分享等热门话题进行了深入的讨论。 汇总…

WordPress 告别 MySQL:Docker SQLite WordPress

本篇文章聊聊&#xff0c;如何将这个持续诞生和维护了 21 年的开源软件“脱离数据库”运行&#xff0c;让它能够更加轻量、适合低成本离线运行。 写在前面 2003 年&#xff0c;Michel Valdrighi 基于 b2/cafelog 创建了开源软件 WordPress&#xff0c;并在 GPL 协议下发布。 …