首页 > 其他分享 >Vitis HLS 学习笔记--函数例化(Function Instantiation)

Vitis HLS 学习笔记--函数例化(Function Instantiation)

时间:2024-06-18 22:58:04浏览次数:20  
标签:Function tmp Instantiation 函数 -- HLS char ap foo

目录

1. 简介

2. 功能分析

3. 示例分析

3.1 不使用 FUNCTION_INSTANTIATE

3.2 使用 FUNCTION_INSTANTIATE

4. 总结


1. 简介

函数例化(Function Instantiation)是 Vitis HLS 中的一个高级优化技术。它允许开发者在保持函数层次结构的同时,对函数的特定实例进行局部优化。如果函数的某些输入参数在调用时是已知的常量,那么可以利用这些信息来简化函数的控制逻辑,从而可能改善延迟和吞吐量。

2. 功能分析

在 Vitis HLS 中的函数,在没有特别指定编译指示的情况下,HLS 工具会遵循以下原则进行处理:

  • 函数保留为独立层级块:每个函数在生成的RTL(寄存器传输级)代码中都会作为一个独立的模块存在。这有助于保持设计的模块化,使得每个函数都可以独立地被验证和复用。
  • 函数分解(或内联)到更高层次的函数中:如果HLS工具决定将一个函数内联到另一个函数中,那么在RTL代码中,原本独立的函数将不再作为单独的模块存在。相反,它的逻辑会被合并到调用它的函数中。这通常是为了优化性能,减少函数调用的开销。
  • 所有实例使用单一RTL实现:如果一个函数被多次调用,每个调用实例在默认情况下都会共享相同的RTL代码块。这有助于减少生成的硬件资源的数量,因为不需要为每个函数调用创建单独的硬件实现。

Function Instantiation 语法:

#pragma HLS FUNCTION_INSTANTIATE variable=<variable>

其中,variable=<variable>:这是必需的实参,用于定义要用作为常量的函数实参。

FUNCTION_INSTANTIATE 编译指示用于为函数的每个实例创建唯一的 RTL 实现,允许根据函数调用对每个实例进行局部最优化。鉴于调用函数时部分函数输入可能是常量,此编译指示可藉此简化周围控制结构,并生成进一步优化的、更小的函数块。

3. 示例分析

3.1 不使用 FUNCTION_INSTANTIATE

char foo(char inval, char incr) {
#pragma HLS INLINE OFF
//#pragma HLS FUNCTION_INSTANTIATE variable = incr
    return inval + incr;
}

void top(char inval1, char inval2, char inval3, char* outval1, char* outval2,
         char* outval3) {
    *outval1 = foo(inval1, 0);
    *outval2 = foo(inval2, 1);
    *outval3 = foo(inval3, 100);
}

经过综合,得到如下文件结构:

可以发现,代码会为 top 中的函数的全部 3 个实例生成函数 foo 的单一 RTL 实现。函数 foo 的每个实例都是以相同方式实现的。这对于函数复用并无影响,并且可以减少函数的每次实例调用所需的面积,但是函数内部的控制逻辑必须更复杂,以便应对每次调用 foo 时产生的变化。

如下代码可以看到每次函数调用的情况:

...

example_foo tmp_foo_fu_79(
    .ap_ready(tmp_foo_fu_79_ap_ready),
    .inval(inval1),
    .incr(6'd0),
    .ap_return(tmp_foo_fu_79_ap_return)
);

example_foo tmp_1_foo_fu_88(
    .ap_ready(tmp_1_foo_fu_88_ap_ready),
    .inval(inval2),
    .incr(6'd1),
    .ap_return(tmp_1_foo_fu_88_ap_return)
);

example_foo tmp_2_foo_fu_97(
    .ap_ready(tmp_2_foo_fu_97_ap_ready),
    .inval(inval3),
    .incr(6'd36),
    .ap_return(tmp_2_foo_fu_97_ap_return)
);

always @ (*) begin
    if ((ap_start == 1'b1)) begin
        outval1_ap_vld = 1'b1;
    end else begin
        outval1_ap_vld = 1'b0;
    end
end

always @ (*) begin
    if ((ap_start == 1'b1)) begin
        outval2_ap_vld = 1'b1;
    end else begin
        outval2_ap_vld = 1'b0;
    end
end

always @ (*) begin
    if ((ap_start == 1'b1)) begin
        outval3_ap_vld = 1'b1;
    end else begin
        outval3_ap_vld = 1'b0;
    end
end

assign ap_done = ap_start;

assign ap_idle = 1'b1;

assign ap_ready = ap_start;

assign outval1 = tmp_foo_fu_79_ap_return;

assign outval2 = tmp_1_foo_fu_88_ap_return;

assign outval3 = tmp_2_foo_fu_97_ap_return;

endmodule //example

3.2 使用 FUNCTION_INSTANTIATE

char foo(char inval, char incr) {
#pragma HLS INLINE OFF
#pragma HLS FUNCTION_INSTANTIATE variable = incr
    return inval + incr;
}

void top(char inval1, char inval2, char inval3, char* outval1, char* outval2,
         char* outval3) {
    *outval1 = foo(inval1, 0);
    *outval2 = foo(inval2, 1);
    *outval3 = foo(inval3, 100);
}

经过综合,得到如下文件结构:

可以发现,代码会为 top 中的函数的由 3 个独立的实例生成函数 foo 的 RTL 实现:example_foo_0.v、example_foo_1.v、example_foo_2.v。

在以上代码样本中:

#pragma HLS FUNCTION_INSTANTIATE variable = incr

FUNCTION_INSTANTIATE 编译指示会生成函数 foo 的 3 个不同实现,每个实现都会按incr 指定值进行最优化,从而减少面积并改善函数实现的性能。

提示:Vitis HLS 工具会将小函数自动分解(或内联)到更高层次的调用函数中。即使对于函数例化也同样如此。将 INLINE 编译指示与 OFF 选项搭配使用即可阻止此自动内联操作。

4. 总结

函数例化是Vitis HLS中的一种高级优化技术,它允许开发者在保持函数层次结构的同时,对特定函数实例进行局部优化。这种技术通过利用编译时已知的常量输入参数,简化函数的控制逻辑,从而可能改善延迟和吞吐量。默认情况下,函数在RTL中作为独立层级块保留,或者分解到更高层次的函数中,所有实例共享单一RTL实现。通过使用FUNCTION_INSTANTIATE编译指示,可以为每个函数调用创建唯一的RTL实现,允许针对每个实例进行局部最优化。这样,即使原始函数包含复杂的控制逻辑,每个实例化的函数也可以被优化以仅包含必要的逻辑,减少硬件资源消耗并提高性能。

标签:Function,tmp,Instantiation,函数,--,HLS,char,ap,foo
From: https://blog.csdn.net/DongDong314/article/details/139756502

相关文章

  • 宠物行业从0~1宠物短视频带货实操课(23节课)
    课程内容:1:线上课试听课_.mov2:1.宠物行业趋势_.mov3:1-1.2你的竞争对手.mov4:1-2抖音萌宠常见的变现形式.mov5:1-2.1星图广告.mov6:1-2.2中视频计划.mov7:1-2.3线下引流.mov8:1-2.4小程序小游戏.mp49:1-2.5挂车带货的形式与渠道.mov10:1-2.5.1为什......
  • 【Spring Cloud应用框架】
    ......
  • 【讲解下Pip换源】
    ......
  • 数据库常见 SQL 语句及语法
    数据库操作创建数据库语法CREATEDATABASEdatabase_name;删除数据库语法DROPDATABASEdatabase_name;选择数据库语法USEdatabase_name;表操作创建表语法CREATETABLEtable_name(column1(字段)datatype(数据类型)constraints(约束条件),column2d......
  • Dynamics CRM 365 验证客户端的网络容量和吞吐量
    如何检查延迟CustomerEngagement应用包括一个基本的诊断工具,用于分析客户端与组织的连接并生成报告。若要运行诊断工具,请按照下列步骤操作。在用户的计算机或设备上,启动Web浏览器,然后登录到组织。输入以下URLhttps://myorg.crm.dynamics.com/tools/diagnostics/diag.asp......
  • 博客园美化教程 可自制(附代码)
    博客美化由于有小伙伴需要这些好看的代码,我就把自己从网上整合的一些代码分享给各位。主要参考了凌云_void大佬的博客申请JS权限第一步你需要申请一个博客,审核通过之后在博客后台的设置中找到申请js权限理由积极向上即可通过后就可以开始后门的步骤了,差不多半个小时审核就......
  • 开始预习数据库第四天下
    你怎么知道我马上要考的数据库(5)开始时间 2024-06-18 20:21:58结束时间 2024-06-18 22:43:55前言:睡醒了假设某大型航空公司数据库,其关系模式(下划线代表主码)有:航班表(航班号,起点,终点,机型,价格,折扣)乘客表(身份证号,姓名,性别,年龄,会员等级)订单表(航班号,身份证号,日期,座位......
  • 实验七
    /将图书信息写入文本文件data1.txt//再从文件中读取图书信息,打印输出到屏幕上,并显示行号#include<stdio.h>#defineN80#defineM100typedefstruct{charname[N];//书名charauthor[N];//作者}Book;//函数声明voidfunc1();voidfunc2()......
  • MySQL常见的后端面试题,你会几道?
     为什么分库分表单表数据量过大,会出现慢查询,所以需要水平分表可以把低频、高频的字段分开为多个表,低频的表作为附加表,且逻辑更加清晰,性能更优随着系统的业务模块的增多,放到单库会增加其复杂度,逻辑不清晰,不好维护,所以会对业务进行微服务拆分,同时拆分数据库怎么分库分......
  • Arduino实现温湿度传感器以及数据上传到云(乐维互联)
    0准备材料0.1ESP-01S引脚及定义官方定义:序号pin功能1GND地线2IO0/GPIO0工作模式选择:①悬空:FlashBoot,工作模式②下拉:UARTDownLoad下载模式3IO2/GPIO2通用IO4RX/RXD数据接收端5TX/TXD谁发送端63V3/VCC3.3V,模块供电7RST1)外......