​​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

相关文章

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. 关键注

C++中函数模板与类模板的简单使用及区别介绍

《C++中函数模板与类模板的简单使用及区别介绍》这篇文章介绍了C++中的模板机制,包括函数模板和类模板的概念、语法和实际应用,函数模板通过类型参数实现泛型操作,而类模板允许创建可处理多种数据类型的类,... 目录一、函数模板定义语法真实示例二、类模板三、关键区别四、注意事项 ‌在C++中,模板是实现泛型编程

kotlin的函数forEach示例详解

《kotlin的函数forEach示例详解》在Kotlin中,forEach是一个高阶函数,用于遍历集合中的每个元素并对其执行指定的操作,它的核心特点是简洁、函数式,适用于需要遍历集合且无需返回值的场... 目录一、基本用法1️⃣ 遍历集合2️⃣ 遍历数组3️⃣ 遍历 Map二、与 for 循环的区别三、高

C语言字符函数和字符串函数示例详解

《C语言字符函数和字符串函数示例详解》本文详细介绍了C语言中字符分类函数、字符转换函数及字符串操作函数的使用方法,并通过示例代码展示了如何实现这些功能,通过这些内容,读者可以深入理解并掌握C语言中的字... 目录一、字符分类函数二、字符转换函数三、strlen的使用和模拟实现3.1strlen函数3.2st

Java进阶学习之如何开启远程调式

《Java进阶学习之如何开启远程调式》Java开发中的远程调试是一项至关重要的技能,特别是在处理生产环境的问题或者协作开发时,:本文主要介绍Java进阶学习之如何开启远程调式的相关资料,需要的朋友... 目录概述Java远程调试的开启与底层原理开启Java远程调试底层原理JVM参数总结&nbsMbKKXJx

MySQL中COALESCE函数示例详解

《MySQL中COALESCE函数示例详解》COALESCE是一个功能强大且常用的SQL函数,主要用来处理NULL值和实现灵活的值选择策略,能够使查询逻辑更清晰、简洁,:本文主要介绍MySQL中C... 目录语法示例1. 替换 NULL 值2. 用于字段默认值3. 多列优先级4. 结合聚合函数注意事项总结C

Java8需要知道的4个函数式接口简单教程

《Java8需要知道的4个函数式接口简单教程》:本文主要介绍Java8中引入的函数式接口,包括Consumer、Supplier、Predicate和Function,以及它们的用法和特点,文中... 目录什么是函数是接口?Consumer接口定义核心特点注意事项常见用法1.基本用法2.结合andThen链

MySQL 日期时间格式化函数 DATE_FORMAT() 的使用示例详解

《MySQL日期时间格式化函数DATE_FORMAT()的使用示例详解》`DATE_FORMAT()`是MySQL中用于格式化日期时间的函数,本文详细介绍了其语法、格式化字符串的含义以及常见日期... 目录一、DATE_FORMAT()语法二、格式化字符串详解三、常见日期时间格式组合四、业务场景五、总结一、

golang panic 函数用法示例详解

《golangpanic函数用法示例详解》在Go语言中,panic用于触发不可恢复的错误,终止函数执行并逐层向上触发defer,最终若未被recover捕获,程序会崩溃,recover用于在def... 目录1. panic 的作用2. 基本用法3. recover 的使用规则4. 错误处理建议5. 常见错