​​Vitis HLS 学习笔记--添加 RTL 黑盒函数

2024-06-16 08:12

本文主要是介绍​​Vitis HLS 学习笔记--添加 RTL 黑盒函数,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

1. 简介

2. 用法详解

2.1 需要的文件

2.1.1 RTL 函数签名

2.1.2 黑盒 JSON 描述文件

2.1.3 RTL IP 文件

2.2 操作步骤

3. 总结


1. 简介

Vitis HLS 工具可以将现有的 Verilog RTL IP(即硬件描述语言编写的模块)集成到 C/C++ HLS 项目中。通过这种方式,Vitis HLS 能够将 RTL 代码与 C/C++ 代码一起综合,形成最终的硬件设计。

RTL 黑盒允许设计者在 HLS 设计中的特定区域(如顺序区域、流水线区域或数据流区域)内使用 Verilog 或 VHDL 编写的 RTL IP。这样做的好处是可以重用现有的硬件模块,同时利用 HLS 的优势来加速整个设计和开发过程。

简单的说,如果你有一个用 Verilog 编写的性能优化好的 IP,可以将其作为黑盒插入到 HLS 项目中,而不需要将其重新用 C/C++ 实现。这样可以节省时间,并确保硬件设计的高效性和可靠性。

2. 用法详解

2.1 需要的文件

2.1.1 RTL 函数签名

RTL 代码的 C 语言函数签名,是指用于代表RTL模块的C函数的声明。这个签名定义了函数的名称、输入参数和返回类型,这样C代码就可以调用它,就像调用任何其他C函数一样。这个签名通常放在一个头文件(.h)中,以便在整个项目中使用。

#include "ap_int.h"//--------------------------------------------------------
//RTL 代码的 C 语言函数签名
//--------------------------------------------------------
void rtl_model(ap_int<10>  a1, ap_int<10>  a2, ap_int<10>  a3, ap_int<10>  a4,ap_int<10>  b1, ap_int<10>  b2, ap_int<10>  b3, ap_int<10>  b4,ap_int<10>& z1, ap_int<10>& z2, ap_int<10>& z3, ap_int<10>& z4);//--------------------------------------------------------
void example(ap_int<10> a1, ap_int<10> a2, ap_int<10> a3, ap_int<10> a4,ap_int<10> b1, ap_int<10> b2, ap_int<10> b3, ap_int<10> b4,ap_int<10>& sigma) {ap_int<10> tmp1, tmp2, tmp3, tmp4;rtl_model(a1, a2, a3, a4, b1, b2, b3, b4, tmp1, tmp2, tmp3, tmp4);sigma = tmp1 + tmp2 + tmp3 + tmp4;
}

2.1.2 黑盒 JSON 描述文件

{
"c_function_name"     : "rtl_model",
"rtl_top_module_name" : "rtl_model",
"c_files" : [{ "c_file" : "rtl_model.cpp","cflag" : ""}],
"rtl_files" : ["rtl_model.v"],
"c_parameters" : [{"c_name" : "a1","c_port_direction" : "in","rtl_ports" : {"data_read_in" : "a1"}},{"c_name" : "a2","c_port_direction" : "in","rtl_ports" : {"data_read_in" : "a2"}},{"c_name" : "a3","c_port_direction" : "in","rtl_ports" : {"data_read_in" : "a3"}},{"c_name" : "a4","c_port_direction" : "in","rtl_ports" : {"data_read_in" : "a4"}},{"c_name" : "b1","c_port_direction" : "in","rtl_ports" : {"data_read_in" : "b1"}},{"c_name" : "b2","c_port_direction" : "in","rtl_ports" : {"data_read_in" : "b2"}},{"c_name" : "b3","c_port_direction" : "in","rtl_ports" : {"data_read_in" : "b3"}},{"c_name" : "b4","c_port_direction" : "in","rtl_ports" : {"data_read_in" : "b4"}},{"c_name" : "z1","c_port_direction" : "out","rtl_ports" : {"data_write_out"   : "z1","data_write_valid" : "z1_ap_vld"}},{"c_name" : "z2","c_port_direction" : "out","rtl_ports" : {"data_write_out"   : "z2","data_write_valid" : "z2_ap_vld"}},{"c_name" : "z3","c_port_direction" : "out","rtl_ports" : {"data_write_out"   : "z3","data_write_valid" : "z3_ap_vld"}},{"c_name" : "z4","c_port_direction" : "out","rtl_ports" : {"data_write_out"   : "z4","data_write_valid" : "z4_ap_vld"}}],
"rtl_common_signal" : {"module_clock"                    : "ap_clk","module_reset"                    : "ap_rst","module_clock_enable"             : "ap_ce","ap_ctrl_chain_protocol_idle"     : "ap_idle","ap_ctrl_chain_protocol_start"    : "ap_start","ap_ctrl_chain_protocol_ready"    : "ap_ready","ap_ctrl_chain_protocol_done"     : "ap_done","ap_ctrl_chain_protocol_continue" : "ap_continue"},
"rtl_performance" : {"latency" : "2","II"      : "1"},
"rtl_resource_usage" : {"FF"   :   "0","LUT"  :   "0","BRAM" :   "0","URAM" :   "0","DSP"  :   "1"}
}

2.1.3 RTL IP 文件

`timescale 100ps/100ps(* use_dsp = "simd" *)
(* dont_touch = "1" *)  
module rtl_model (input            ap_clk, ap_rst, ap_ce, ap_start, ap_continue,input [9:0]      a1, a2, a3, a4, b1, b2, b3, b4,output           ap_idle, ap_done, ap_ready,output           z1_ap_vld, z2_ap_vld, z3_ap_vld, z4_ap_vld,output reg [9:0] z1,        z2,        z3,        z4);wire ce = ap_ce;reg [9:0] areg1, areg2, areg3, areg4;reg [9:0] breg1, breg2, breg3, breg4;reg       dly1, dly2;always @ (posedge ap_clk)if (ap_rst)beginz1    <= 0;z2    <= 0;z3    <= 0;z4    <= 0;areg1 <= 0;areg2 <= 0;areg3 <= 0;areg4 <= 0;breg1 <= 0;breg2 <= 0;breg3 <= 0;breg4 <= 0;dly1  <= 0;dly2  <= 0;     endelse if (ce)beginz1    <= areg1 + breg1;z2    <= areg2 + breg2;z3    <= areg3 + breg3;z4    <= areg4 + breg4;areg1 <= a1;areg2 <= a2;areg3 <= a3;areg4 <= a4;breg1 <= b1;breg2 <= b2;breg3 <= b3;breg4 <= b4;dly1  <= ap_start;dly2  <= dly1;          endassign z1_ap_vld = dly2;assign z2_ap_vld = dly2;assign z3_ap_vld = dly2;assign z4_ap_vld = dly2;assign ap_ready  = dly2;assign ap_done   = dly2;assign ap_idle   = ~ap_start;endmodule // rtl_model

2.2 使用 RTL 黑盒向导

整体步骤和常规的 Vitis HLS 步骤一致,特殊点在于多了一个 JSON 文件需要配置:

  • 从顶层函数内或者从 Vitis HLS 工程的子函数内调用 C 语言函数签名。
  • 在 Vitis HLS IDE 中使用“Add Files”(添加文件),将黑盒 JSON 描述文件添加到 HLS 工程中。
  • 运行 Vitis HLS 设计文件照常进行仿真、综合和协同仿真。

使用 RTL 黑盒向导操作步骤:

在导航到工程中,打开 RTL 黑盒向导:

 

3. 总结

Vitis HLS 的引入为硬件设计师提供了一种灵活高效的设计途径,通过允许 RTL 黑盒的使用,设计师可以在不牺牲性能的前提下,重用现有的硬件模块,同时利用 HLS 的高层次抽象和快速迭代能力来加速设计和开发过程。这种方法既节省了将硬件模块重新用 C/C++ 实现的时间,也保持了设计的高效性和可靠性。通过简化操作步骤和提供直观的工具,如 RTL Blackbox Wizard,Vitis HLS 降低了硬件设计的复杂性,使得开发者能够更加专注于创新和优化。

这篇关于​​Vitis HLS 学习笔记--添加 RTL 黑盒函数的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1065915

相关文章

shell编程之函数与数组的使用详解

《shell编程之函数与数组的使用详解》:本文主要介绍shell编程之函数与数组的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录shell函数函数的用法俩个数求和系统资源监控并报警函数函数变量的作用范围函数的参数递归函数shell数组获取数组的长度读取某下的

MySQL高级查询之JOIN、子查询、窗口函数实际案例

《MySQL高级查询之JOIN、子查询、窗口函数实际案例》:本文主要介绍MySQL高级查询之JOIN、子查询、窗口函数实际案例的相关资料,JOIN用于多表关联查询,子查询用于数据筛选和过滤,窗口函... 目录前言1. JOIN(连接查询)1.1 内连接(INNER JOIN)1.2 左连接(LEFT JOI

MySQL中FIND_IN_SET函数与INSTR函数用法解析

《MySQL中FIND_IN_SET函数与INSTR函数用法解析》:本文主要介绍MySQL中FIND_IN_SET函数与INSTR函数用法解析,本文通过实例代码给大家介绍的非常详细,感兴趣的朋友一... 目录一、功能定义与语法1、FIND_IN_SET函数2、INSTR函数二、本质区别对比三、实际场景案例分

利用Python快速搭建Markdown笔记发布系统

《利用Python快速搭建Markdown笔记发布系统》这篇文章主要为大家详细介绍了使用Python生态的成熟工具,在30分钟内搭建一个支持Markdown渲染、分类标签、全文搜索的私有化知识发布系统... 目录引言:为什么要自建知识博客一、技术选型:极简主义开发栈二、系统架构设计三、核心代码实现(分步解析

C++ Sort函数使用场景分析

《C++Sort函数使用场景分析》sort函数是algorithm库下的一个函数,sort函数是不稳定的,即大小相同的元素在排序后相对顺序可能发生改变,如果某些场景需要保持相同元素间的相对顺序,可使... 目录C++ Sort函数详解一、sort函数调用的两种方式二、sort函数使用场景三、sort函数排序

C语言函数递归实际应用举例详解

《C语言函数递归实际应用举例详解》程序调用自身的编程技巧称为递归,递归做为一种算法在程序设计语言中广泛应用,:本文主要介绍C语言函数递归实际应用举例的相关资料,文中通过代码介绍的非常详细,需要的朋... 目录前言一、递归的概念与思想二、递归的限制条件 三、递归的实际应用举例(一)求 n 的阶乘(二)顺序打印

C/C++错误信息处理的常见方法及函数

《C/C++错误信息处理的常见方法及函数》C/C++是两种广泛使用的编程语言,特别是在系统编程、嵌入式开发以及高性能计算领域,:本文主要介绍C/C++错误信息处理的常见方法及函数,文中通过代码介绍... 目录前言1. errno 和 perror()示例:2. strerror()示例:3. perror(

Kotlin 作用域函数apply、let、run、with、also使用指南

《Kotlin作用域函数apply、let、run、with、also使用指南》在Kotlin开发中,作用域函数(ScopeFunctions)是一组能让代码更简洁、更函数式的高阶函数,本文将... 目录一、引言:为什么需要作用域函数?二、作用域函China编程数详解1. apply:对象配置的 “流式构建器”最

Android Kotlin 高阶函数详解及其在协程中的应用小结

《AndroidKotlin高阶函数详解及其在协程中的应用小结》高阶函数是Kotlin中的一个重要特性,它能够将函数作为一等公民(First-ClassCitizen),使得代码更加简洁、灵活和可... 目录1. 引言2. 什么是高阶函数?3. 高阶函数的基础用法3.1 传递函数作为参数3.2 Lambda

C++中::SHCreateDirectoryEx函数使用方法

《C++中::SHCreateDirectoryEx函数使用方法》::SHCreateDirectoryEx用于创建多级目录,类似于mkdir-p命令,本文主要介绍了C++中::SHCreateDir... 目录1. 函数原型与依赖项2. 基本使用示例示例 1:创建单层目录示例 2:创建多级目录3. 关键注