FPGA学习笔记#8 Vitis HLS优化总结和案例程序的优化

本笔记使用的Vitis HLS版本为2022.2,在windows11下运行,仿真part为xcku15p_CIV-ffva1156-2LV-e,主要根据教程:跟Xilinx SAE 学HLS系列视频讲座-高亚军进行学习


学习笔记:《FPGA学习笔记》索引
FPGA学习笔记#1 HLS简介及相关概念
FPGA学习笔记#2 基本组件——CLB、SLICE、LUT、MUX、进位链、DRAM、存储单元、BRAM
FPGA学习笔记#3 Vitis HLS编程规范、数据类型、基本运算
FPGA学习笔记#4 Vitis HLS 入门的第一个工程
FPGA学习笔记#5 Vitis HLS For循环的优化(1)
FPGA学习笔记#6 Vitis HLS For循环的优化(2)
FPGA学习笔记#7 Vitis HLS 数组优化和函数优化
FPGA学习笔记#8 Vitis HLS优化总结和案例程序的优化


目录

  • 1.HLS优化总结
  • 2.优化案例
  •     2.1.案例程序
  •     2.2.案例优化

1.HLS优化总结

对于函数,可以使用PIPELINE或DATAFLOW。

对于循环,可以使用PIPELINE(可选rewind)、UNROLL(可选factor)或DATAFLOW。

对于数组,可以使用ARRAY_PARTITION,有block、cyclic、complete三种优化方式。

PIPELINE作用于函数和循环的情况如下,作用于循环时,两次循环之间会存在空档,被称为bubble,rewind可以解决这个问题。

对于latency,有专门的LATENCY约束用于函数和循环,可以指定min和max。

LOOP_MERGE用于合并多个循环

LOOP_FLATTEN用于perfect/semi-perfect循环

在区域中:
数据类型和位宽也是影响硬件效率和资源使用的原因
INLINE用于函数
ALLOCATION用于函数的实例化
ARRAY_MAP和ARRAY_RESHAPE用于数组
FUNCTION_INSTANTIATE用于函数


2.优化案例

2.1.案例程序

案例程序如下,请根据第四篇笔记进行项目的构建和仿真、综合、联合仿真。

Top.h:

#include <ap_int.h>
#include <ap_fixed.h>

#define WA 17
#define FA 14
#define WS 16
#define FS 14

typedef ap_fixed<WA,WA-FA> di_t;
typedef ap_fixed<WS,WS-FS> do_t;
typedef ap_uint<2> flag_t;

const do_t Kn = 0.607252935;
const di_t PI = 3.1415926;

void cir_cordic (di_t full_alpha, do_t &out_sin, do_t &out_cos);

Top.cpp:

#include "top.h"
 
void pre_cir_cordic (di_t full_alpha, di_t &alpha, flag_t &flag)
{
    if (full_alpha > PI/2)
    {
        alpha = PI - full_alpha;
        flag = 2;
    }
    else if (full_alpha < -PI/2)
    {
        alpha = -PI - full_alpha;
        flag = 3;
    }
    else
    {
        alpha = full_alpha;
        flag = 0;
    }
}

void cir_cordic_calculate (di_t alpha, flag_t flag, do_t &mysin, do_t &mycos, flag_t &flag_delay)
{
    const int N = 16;
    do_t xi[N];
    do_t yi[N];
    di_t zi[N];
flag_t flag_delay_a[N];

    xi[0] = Kn;
    yi[0] = 0;
    zi[0] = alpha;
flag_delay_a[0] = flag;

    const di_t myarctan[16] = {
        0.7853981633974483, 
        0.4636476090008061, 
        0.24497866312686414, 
        0.12435499454676144, 
        0.06241880999595735, 
        0.031239833430268277, 
        0.015623728620476831, 
        0.007812341060101111, 
        0.0039062301319669718, 
        0.0019531225164788188, 
        0.0009765621895593195, 
        0.0004882812111948983, 
        0.00024414062014936177, 
        0.00012207031189367021, 
        6.103515617420877e-05, 
        3.0517578115526096e-05
    };
    int m = 0;
loop:
    for (m = 0; m < N; m++)
    {
        if (zi[m] >= 0)
        {
            xi[m+1] = xi[m] - (yi[m] >> m);
            yi[m+1] = yi[m] + (xi[m] >> m);
            zi[m+1] = zi[m] - myarctan[m];
        }
        else
        {
            xi[m+1] = xi[m] + (yi[m] >> m);
            yi[m+1] = yi[m] - (xi[m] >> m);
            zi[m+1] = zi[m] + myarctan[m];
        }
        flag_delay_a[m+1] = flag_delay_a[m];
    }
    mysin = yi[N-1];
    mycos = xi[N-1];
    flag_delay = flag_delay_a[N-1];
}

void post_cir_cordic (do_t mysin, do_t mycos, flag_t flag_delay, do_t &sin_out, do_t &cos_out)
{
    switch(int(flag_delay))
    {
        case 2: sin_out = mysin; cos_out = -mycos; break;
        case 3: sin_out = -mysin; cos_out = -mycos; break;
        default: sin_out = mysin; cos_out = mycos; break;
    }
}

void cir_cordic (di_t full_alpha, do_t &out_sin, do_t &out_cos)
{
    di_t alpha;
    flag_t flag;
    do_t mysin;
    do_t mycos;
flag_t flag_delay;

    pre_cir_cordic(full_alpha, alpha, flag);
    cir_cordic_calculate(alpha, flag, mysin, mycos, flag_delay);
    post_cir_cordic(mysin, mycos, flag_delay, out_sin, out_cos);
}

Test.cpp:

#include <iostream>
#include <iomanip>
#include <cmath>
#include <math.h>
#include "top.h"

using namespace std;

int main(){
    const int N = 13;
    di_t alpha[N] = {
        3.01837,
        3.02838,
        3.03839,
        3.0484,
        3.05835,
        3.06836,
        3.07837,
        3.08838,
        3.09839,
        3.1084,
        3.11835,
        3.12836,
        3.13837
    };
    do_t sinRef[N] = {
        0.122864,
        0.112915,
        0.102966,
        0.0930176,
        0.0830688,
        0.0730591,
        0.0631104,
        0.0531006,
        0.0431519,
        0.0331421,
        0.0231323,
        0.0131836,
        0.00317383
    };
    do_t cosRef[N] = {
        -0.992432,
        -0.993652,
        -0.99469,
        -0.995667,
        -0.996582,
        -0.997375,
        -0.998047,
        -0.998596,
        -0.999084,
        -0.999451,
        -0.999756,
        -0.999939,
        -1.0
    };
    do_t sinres[N] = {0};
    do_t cosres[N] = {0};
    int ErrCntSin = 0;
    int ErrCntCos = 0;
    float precision = pow(2, -10);
int i;

    for (i = 0; i < N; i++)
    {
        cir_cordic(alpha[i], sinres[i], cosres[i]);
}

    cout << setfill('-') << setw(90) << "-" << endl;
    cout << setfill(' ') << setw(18) << right << "Alpha";
    cout << setfill(' ') << setw(18) << right << "sin";
    cout << setfill(' ') << setw(18) << right << "sinRef";
    cout << setfill(' ') << setw(18) << right << "cos";
    cout << setfill(' ') << setw(18) << right << "cosRef" << endl;
cout << setfill('-') << setw(90) << "-" << endl;

    for (i = 0; i < N; i++)
    {
        cout << setfill(' ') << setw(18) << right << alpha[i];
        cout << setfill(' ') << setw(18) << right << sinres[i];
        cout << setfill(' ') << setw(18) << right << sinRef[i];
        cout << setfill(' ') << setw(18) << right << cosres[i];
        cout << setfill(' ') << setw(18) << right << cosRef[i];

        if (abs(float(sinres[i] - sinRef[i])) > precision)
        {
            ErrCntSin++;
            cout << setfill(' ') << setw(18) << right << "(sin failed)";
        }
        if (abs(float(cosres[i] - cosRef[i])) > precision)
        {
            ErrCntCos++;
            cout << setfill(' ') << setw(18) << right << "(cos failed)";
        }
        cout << endl;
}

cout << setfill('-') << setw(90) << "-" << endl;

    if (ErrCntSin + ErrCntCos == 0)
    {
        cout << "Test passed!" << endl;
        return 0;
    }
    else
    {
        cout << "Test failed!" << endl;
        cout << "sin failed: " << ErrCntSin << endl;
        cout << "cos failed: " << ErrCntCos << endl;
        return 1;
    }
}

2.2.案例优化

对案例程序进行综合,得到Performance结果,注意新版本的Vitis已经自动打上了PIPELINE,旧版本可能比这要慢:

现在创建一个新的solution,给代码中打了loop标签的循环设置PIPELINE或UNROLL。

这里原教程是两个一块打开,我发现会报错冲突,因此我分别对这个循环测试了PIPELINE和UNROLL的优化结果。

单独开启PIPELINE的结果,因为默认也是打开的,所以没变化:

单独开启UNROLL的结果,latency大幅降低,同时很明显的LUT使用量也变高:

接下来我们在开启UNROLL的基础上创建新solution,在对循环UNROLL的同时,给top函数打上PIPELINE:

会发现interval进一步变为了1:

对比三次结果:

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

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

相关文章

替代CX8835车充5V/3.4A恒流恒压降压转换器内置MOS

概述&#xff1a;PIN对PIN替代CX8835 PC3313是宽输入电压&#xff0c;高效率有源CC降压DC/DC转换器&#xff0c;可以在CV&#xff08;恒压&#xff09;或CC模式下运行&#xff08;恒流&#xff09;输出模式。PC3313在5V输出时提供高达典型3.4A的电流限制带有18mΩ电流感测电阻…

2024年8个最佳在线websocket调试工具选择

精选了 8 款功能强大且易于使用的 WebSocket 测试工具&#xff1a; 工具名称支持的系统是否免费ApifoxWindows, Mac, Linux是WebSocket KingWindows, Mac, Linux是PostmanWindows, Mac, Linux是Socket.IO Test ClientWindows, Mac, Linux是InsomniaWindows, Mac, Linux是Wires…

ML 系列:第 21 节 — 离散概率分布(二项分布)

一、说明 二项分布描述了在固定数量的独立伯努利试验中一定数量的成功的概率&#xff0c;其中每个试验只有两种可能的结果&#xff08;通常标记为成功和失败&#xff09;。 二、探讨伯努利模型 例如&#xff0c;假设您正在抛一枚公平的硬币 &#xff08;其中正面成功&#xff…

2024开发者浏览器必备扩展,不允许还有人不知道~

在开发过程中&#xff0c;优秀的扩展工具能够极大提升我们的工作效率&#xff0c;简化工作流程&#xff0c;并使得在浏览器中的开发和调试变得更加便捷。 根据市场占比&#xff0c;Chrome、Safari、Edge、Firefox、Opera 是前五大浏览器&#xff0c;其中Chrome浏览器占据了领先…

安装paddle

网址&#xff1a;飞桨PaddlePaddle-源于产业实践的开源深度学习平台 或者找对应python和cuda版本的paddle下载后安装&#xff1a; https://www.paddlepaddle.org.cn/whl/linux/mkl/avx/stable.html 你想要安装paddlepaddle - gpu2.6.1.post112版本。在你提供的文件列表中&am…

(六)Spark大数据开发实战:豆瓣电影数据处理与分析(scala版)

目录 一、Spark 二、数据介绍 三、Spark大数据开发实战(Scala) 1、数据文件上传HDFS 2、导入模块及数据 3、数据统计与分析 ①、计算演员参演电影数 ②、依次罗列电影番位前十的演员 ③、按照番位计算演员参演电影数 ④、求每位演员所有参演电影中的最早、最晚上映…

‘nodemon‘ 不是内部或外部命令,也不是可运行的程序

解决方法&#xff1a;使用 npx 临时运行 nodemon 如果你不想全局安装 nodemon&#xff0c;你可以使用 npx&#xff08;npm 5.2 及以上版本自带&#xff09;来临时运行 nodemon&#xff1a; npx nodemon server.jsnodemon正常配置 要在开发过程中实现每次修改 Node.js 代码后…

Docker 的安装与使用

Docker 的安装 Docker 是一个开源的商业产品&#xff0c;有两个版本&#xff1a;社区版&#xff08;Community Edition&#xff0c;缩写为 CE&#xff09;和企业版&#xff08;Enterprise Edition&#xff0c;缩写为 EE&#xff09;。 Docker CE 的安装请参考官方文档&#xf…

单相锁相环,原理与Matlab实现

单相锁相环基本原理 单相锁相环的基本原理图如下所示&#xff0c; u α u_\alpha uα​ u β u_\beta uβ​经Park变换、PI控制实现对角频率 ω \omega ω和角度 θ \theta θ的估算。不同锁相环方案之间的差异&#xff0c;主要表现在正交电压 u β u_\beta uβ​的生成&#x…

LLMs之PDF:zeroX(一款PDF到Markdown 的视觉模型转换工具)的简介、安装和使用方法、案例应用之详细攻略

LLMs之PDF&#xff1a;zeroX(一款PDF到Markdown 的视觉模型转换工具)的简介、安装和使用方法、案例应用之详细攻略 目录 zeroX的简介 1、支持的文件类型 zeroX的安装和使用方法 T1、Node.js 版本&#xff1a; 安装 使用方法 使用文件 URL&#xff1a; 使用本地路径&…

Redis集群模式之Redis Sentinel vs. Redis Cluster

在分布式系统环境中&#xff0c;Redis以其高性能、低延迟和丰富的数据结构而广受青睐。随着数据量的增长和访问需求的增加&#xff0c;单一Redis实例往往难以满足高可用性和扩展性的要求。为此&#xff0c;Redis提供了两种主要的集群模式&#xff1a;Redis Sentinel和Redis Clu…

OPENCV手把手入门 多图![more cpp--9]

你说安装&#xff1f;楼主使用的是VCPKG&#xff0c;也是遇到不少问题&#xff0c;不过最后还是解决了。大家有需要我抽时间写一篇如何使用VCPKG和VS安装OPENCV出来 最近楼主在做视觉识别方面的工作&#xff0c;这个就当笔记了吧&#xff08;一年前做过这方面的工作&#xff0c…

AI写作(二)NLP:开启自然语言处理的奇妙之旅(2/10)

一、NLP 的基本概念与任务 &#xff08;一&#xff09;自然语言处理的研究对象 自然语言处理&#xff08;NLP&#xff09;处于计算机科学、人工智能和语言学的交叉领域。它所聚焦的人类社会语言信息是无比丰富和复杂的&#xff0c;包括口语、书面语等各种形式。这种语言信息在…

pgsql 版本升级和数据迁移(编译版)

最近给pgsql从16.0升级到16.4&#xff0c;有挺多细节 1.关闭pgsql 为了保证数据一致性和过渡平稳&#xff0c;还是需要暂停pgsql。 systemctl stop pgsql2.备份现有数据 需要切换到pgsql的用户&#xff0c;通常用root是不行的 pg_dumpall > /xxx/xxx/backup.sql3.重命名…

ArcGIS地理空间平台 manager 任意文件读取漏洞复现

0x01 产品描述&#xff1a; ‌ ArcGIS‌是一个综合的地理空间平台&#xff0c;由Esri开发&#xff0c;旨在为专业人士和组织提供全面的地理信息系统&#xff08;GIS&#xff09;功能。ArcGIS通过集成和连接地理环境中的数据&#xff0c;支持创建、管理、分析、映射和共享…

自定义springCloudLoadbalancer简述

概述 目前后端用的基本都是springCloud体系&#xff1b; 平时在dev环境开发时&#xff0c;会把自己的本地服务也注册上去&#xff0c;但是这样的话&#xff0c;在客户端调用时请求可能会打到自己本地&#xff0c;对客户端测试不太友好. 思路大致就是前端在请求头传入指定ip&a…

华为数通HCIA系列第5次考试-【2024-46周-周一】

文章目录 1、子网掩码有什么作用&#xff0c;和IP地址是什么关系&#xff0c;利用子网掩码可以获取哪些信息&#xff1f;2、已知一个IP地址是192.168.1.1&#xff0c;子网掩码是255.255.255.0&#xff0c;求其网络地址3、已知某主机的IP地址是192.168.100.200&#xff0c;子网掩…

[AGC016D] XOR Replace 题解

[AGC016D] XOR Replace 来自 qzmoot 同一机房的同学的题解。 模拟赛用不同的思路场切了。 题面大意&#xff1a;一个序列&#xff0c;一次操作可以将某个位置变成整个序列的异或和。 问最少几步到达目标序列。 来自梦熊的题面&#xff1a; 有一个长度为 n n n 的序列 a …

ubuntu 24.04运行chattts时cuda安装错误原因分析

使用ubuntu 24.04&#xff0c;按照2noise/ChatTTS官方流程安装依赖时报错。ChatTTShttps://github.com/2noise/ChatTTS 这是因为cuda版本不对&#xff0c;ChatTTS目前的版本&#xff0c;要求支持cuda 12.4及以上&#xff0c;但是如果nvidia显卡驱动版本较老&#xff0c;无法支…

力扣-Hot100-技巧【算法学习day.31】

前言 ###我做这类文档一个重要的目的还是给正在学习的大家提供方向&#xff08;例如想要掌握基础用法&#xff0c;该刷哪些题&#xff1f;&#xff09;我的解析也不会做的非常详细&#xff0c;只会提供思路和一些关键点&#xff0c;力扣上的大佬们的题解质量是非常非常高滴&am…