Vitis HLS 学习笔记--控制驱动TLP-处理deadlock

news2024/12/26 10:56:36

目录

1. 简介

2. 代码解析

2.1 HLS kernel代码

2.2 查看接口报告

2.3 TestBench

2.4 Dataflow 报告

3. Takeaways

4. 总结


1. 简介

本文是对《Hardware Acceleration Tutorials: FIFO Sizing for Performance and Avoiding Deadlocks》实验内容的详细解释。

首先需要了解,鉴于数据流优化具有动态特性,且不同并行任务的执行速度各不相同,设置不当的数据流通道可能会引发性能下降或死锁。

数据流通道有两种:FIFO 和 PIPO。可以由工具推断,或者用户自行创建。

FIFO:

  • Streams (including hls::streams and streamed arrays),用户创建。
  • Scalar propagation FIFOs,工具推断。
  • Streams of blocks,用户创建。

每个通道都有自己的握手信号。因为:

  • 它们的读写操作是被调度的。
  • 它们的读/写信号分别由流水线控制或有限状态机(FSM)单独驱动。
  • 它们的full_n/empty_n信号直接使流水线的单个迭代或FSM的状态暂停。

PIPO:

  • PIPO,用户创建。
  • Task Level FIFOs (TLF),工具推断。
  • Input and output ports to the upper level,用户创建。

其中,Task Level FIFOs (TLF) 是标量(scalar)FIFO,其连接到生产者的“done”握手信号以进行写入,并连接到消费者的“start”握手信号以进行读取。这些类型的FIFO是由工具自动推断的。由于底层同步机制的缘故,它们被视为类PIPO。

这些通道应该被视为“使用ap_ctrl_chain握手的通道”,因为:

  • 它们的写入和读取操作不会被调度。它们隐式地与进程的“done”握手或“start”握手相关联。
  • 它们的写入和读取信号分别连接到ap_done和ap_ready。
  • 它们的full_n和empty_n分别连接到ap_continue和ap_start。

总结一下,在分析存储深度、性能、死锁等方面,真正需要关系的是:

  • 通道是否拥有自己的握手机制(FIFOs)。它们的访问在其进程执行期间被分散开来。例如,你可以在管道的第一个II之外读取一个FIFO,或者甚至在数据流网络的最后一个过程中读取。
  • 通道是否通过ap_ctrl_chain进行握手(PIPOs)。它们的读取必须在管道的第一个II中,或者在数据流网络的第一个“层级”的过程中进行,类似地,它们的写入必须在最后一个II或在最后一个“层级”中进行。
  • 另一个区别基于一次操作中传输的数据量,这对于资源分析比对性能分析更为重要:对于PIPOs来说是数组,对于流来说是块流、标量流,对于标量传播FIFOs和任务级FIFOs来说是标量。

2. 代码解析

2.1 HLS kernel代码

#include "example.h"

void example(hls::stream<int>& A, hls::stream<int>& B){
#pragma HLS dataflow
#pragma HLS INTERFACE ap_fifo port=A
#pragma HLS INTERFACE ap_fifo port=B
    hls::stream<int> data_channel1;
    hls::stream<int> data_channel2;

    proc_1(A, data_channel1, data_channel2);
    proc_2(data_channel1, data_channel2, B);
}

void proc_1(hls::stream<int>& A, hls::stream<int>& B, hls::stream<int>& C){
#pragma HLS dataflow
    hls::stream<int> data_channel1;
    hls::stream<int> data_channel2;

    proc_1_1(A, data_channel1, data_channel2);
    proc_1_2(B, C, data_channel1, data_channel2);
}

void proc_1_1(hls::stream<int>& A, hls::stream<int>& data_channel1, hls::stream<int>& data_channel2){
  int i;
  int tmp;
  for(i = 0; i < 10; i++){
    tmp = A.read();
    data_channel1.write(tmp); 
  }
  for(i = 0; i < 10; i++){
    data_channel2.write(tmp); 
  }
}

void proc_1_2(hls::stream<int>& B, hls::stream<int>& C, hls::stream<int>& data_channel1, hls::stream<int>& data_channel2){
  int i;
  int tmp;
  
  for(i = 0; i < 10; i++){
    tmp = data_channel2.read() + data_channel1.read();
    B.write(tmp);
  }
  for(i = 0; i < 10; i++){
    C.write(tmp); 
  }
}

void proc_2(hls::stream<int>& A, hls::stream<int>& B, hls::stream<int>& C){
#pragma HLS dataflow
    hls::stream<int> data_channel1;
    hls::stream<int> data_channel2;

    proc_2_1(A, B, data_channel1, data_channel2);
    proc_2_2(C, data_channel1, data_channel2);
}

void proc_2_1(hls::stream<int>& A, hls::stream<int>& B, hls::stream<int>& data_channel1, hls::stream<int>& data_channel2){
  int i;
  int tmp;
  for(i = 0; i < 10; i++){
    tmp = A.read() + B.read();
    data_channel1.write(tmp); 
  }
  for(i = 0; i < 10; i++){
    data_channel2.write(tmp); 
  }
}

void proc_2_2(hls::stream<int>& C, hls::stream<int>& data_channel1, hls::stream<int>& data_channel2){
  int i;
  int tmp;
  for(i = 0; i < 10; i++){
    tmp = data_channel2.read() + data_channel1.read();
    C.write(tmp);
  }
}

与原示例相比,去掉了“&”符号。

#pragma HLS INTERFACE ap_fifo port=&A
#pragma HLS INTERFACE ap_fifo port=&B

以上 kernel 的功能框图:

2.2 查看接口报告

对于顶层文件,可以查看 example_csynth.rpt,观察顶层接口:

================================================================
== Interface
================================================================
* Summary: 
+-----------+-----+-----+------------+--------------+--------------+
| RTL Ports | Dir | Bits|  Protocol  | Source Object|    C Type    |
+-----------+-----+-----+------------+--------------+--------------+
|A_dout     |   in|   32|     ap_fifo|             A|       pointer|
|A_empty_n  |   in|    1|     ap_fifo|             A|       pointer|
|A_read     |  out|    1|     ap_fifo|             A|       pointer|
|B_din      |  out|   32|     ap_fifo|             B|       pointer|
|B_full_n   |   in|    1|     ap_fifo|             B|       pointer|
|B_write    |  out|    1|     ap_fifo|             B|       pointer|
|ap_clk     |   in|    1|  ap_ctrl_hs|       example|  return value|
|ap_rst     |   in|    1|  ap_ctrl_hs|       example|  return value|
|ap_start   |   in|    1|  ap_ctrl_hs|       example|  return value|
|ap_done    |  out|    1|  ap_ctrl_hs|       example|  return value|
|ap_ready   |  out|    1|  ap_ctrl_hs|       example|  return value|
|ap_idle    |  out|    1|  ap_ctrl_hs|       example|  return value|
+-----------+-----+-----+------------+--------------+--------------+

 针对 Dataflow 区域的每个函数体,均有对应的 Interface:

================================================================
== Interface
================================================================
* Summary: 
+-------------------------------+-----+-----+------------+----------------+--------------+
|           RTL Ports           | Dir | Bits|  Protocol  |  Source Object |    C Type    |
+-------------------------------+-----+-----+------------+----------------+--------------+
|ap_clk                         |   in|    1|  ap_ctrl_hs|        proc_1_1|  return value|
|ap_rst                         |   in|    1|  ap_ctrl_hs|        proc_1_1|  return value|
|ap_start                       |   in|    1|  ap_ctrl_hs|        proc_1_1|  return value|
|start_full_n                   |   in|    1|  ap_ctrl_hs|        proc_1_1|  return value|
|ap_done                        |  out|    1|  ap_ctrl_hs|        proc_1_1|  return value|
|ap_continue                    |   in|    1|  ap_ctrl_hs|        proc_1_1|  return value|
|ap_idle                        |  out|    1|  ap_ctrl_hs|        proc_1_1|  return value|
|ap_ready                       |  out|    1|  ap_ctrl_hs|        proc_1_1|  return value|
|start_out                      |  out|    1|  ap_ctrl_hs|        proc_1_1|  return value|
|start_write                    |  out|    1|  ap_ctrl_hs|        proc_1_1|  return value|
|A_dout                         |   in|   32|     ap_fifo|               A|       pointer|
|A_empty_n                      |   in|    1|     ap_fifo|               A|       pointer|
|A_read                         |  out|    1|     ap_fifo|               A|       pointer|
|data_channel12_din             |  out|   32|     ap_fifo|  data_channel12|       pointer|
|data_channel12_num_data_valid  |   in|    2|     ap_fifo|  data_channel12|       pointer|
|data_channel12_fifo_cap        |   in|    2|     ap_fifo|  data_channel12|       pointer|
|data_channel12_full_n          |   in|    1|     ap_fifo|  data_channel12|       pointer|
|data_channel12_write           |  out|    1|     ap_fifo|  data_channel12|       pointer|
|data_channel23_din             |  out|   32|     ap_fifo|  data_channel23|       pointer|
|data_channel23_num_data_valid  |   in|    2|     ap_fifo|  data_channel23|       pointer|
|data_channel23_fifo_cap        |   in|    2|     ap_fifo|  data_channel23|       pointer|
|data_channel23_full_n          |   in|    1|     ap_fifo|  data_channel23|       pointer|
|data_channel23_write           |  out|    1|     ap_fifo|  data_channel23|       pointer|
+-------------------------------+-----+-----+------------+----------------+--------------+

上述报告 Source  Object 所在列:

  • A - > hls::stream<int>& A, C type 为 pointer
  • data_channel12 -> hls::stream<int>& data_channel1, C type 为 pointer
  • data_channel23 -> hls::stream<int>& data_channel2, C type 为 pointer
​
void proc_1_1(hls::stream<int>& A, hls::stream<int>& data_channel1, hls::stream<int>& data_channel2){
  int i;
  int tmp;
  for(i = 0; i < 10; i++){
    tmp = A.read();
    data_channel1.write(tmp);
  }
  for(i = 0; i < 10; i++){
    data_channel2.write(tmp);
  }
}

2.3 TestBench

#include <stdio.h>
#include "hls_stream.h"

#define SIZE 10
extern void example(hls::stream<int>& A, hls::stream<int>& B);

int main()
{
  int i;
  hls::stream<int> A;
  hls::stream<int> B;
  
  int time = 0;
  for   (time = 0 ; time < 4; time ++) {
      for(i=0; i < SIZE; i++){
        A << (i + time);
      }
      example(A,B);
  }
  return 0;
}

2.4 Dataflow 报告

运行 C Synthesis 后,可以查看 Dataflow 报告,如下图,没有问题。

在运行 C/RTL Cosimulation 后,同样在 Dataflow 报告中可以看到错误。

3. Takeaways

总结而言,Dataflow查看器实现了以下吞吐量分析任务:

图表展示了 DATAFLOW 区域的整体拓扑结构,并显示了在 DATAFLOW 区域中任务之间用于通信的通道类型(FIFO/PIPO)。通过分析每个通道和进程,可以有效地解决死锁或由于FIFO大小不当导致的吞吐量不足等问题。

协同仿真数据通过在仿真过程中跟踪FIFO的最大使用量,为解决FIFO大小设置问题提供了参考依据,从而帮助用户调整FIFO大小。此外,运行协同仿真时的自动死锁检测功能能够突出显示涉及死锁的进程和通道,使用户能够快速定位并解决这些问题。

除了 FIFO 大小的调整,协同仿真后的数据还能按每个进程和通道报告因等待输入或输出而导致的停滞时间。这些图表帮助用户理解并解决这些问题,同时管理通道大小以满足慢速生产者与快速消费者之间的需求,或者相反。此外,图表还揭示了在DATAFLOW区域中途读取输入如何影响整体性能,这是一个常见的场景,可能会对性能产生重大影响。

4. 总结

在数据流优化中,通道类型、握手机制、FIFO大小和死锁避免都是关键因素。通过Dataflow查看器和协同仿真数据,您可以有效地优化设计,提高性能并避免潜在问题。

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

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

相关文章

AI视频教程下载:用提示工程在GPT商店构建10个GPTs

你将学到什么&#xff1f; 深入了解ChatGPT平台和GPT商店的生态系统。 开发为多样化应用定制GPT模型的专业知识。 掌握高效内容生成的AI自动化技术。 学习高级提示工程以优化ChatGPT输出。 获取构建AI驱动的数字营销和广告解决方案的技能。 了解如何为SEO写作和优化创建专…

从0开始学统计-多个婴儿连续夭折是谋杀吗?

1.什么是小概率事件&#xff1f; 小概率事件是指在一次随机试验中发生概率非常低的事件。一般来说&#xff0c;小概率事件的发生概率远低于一定的阈值&#xff0c;通常取0.05或0.01。在统计学中&#xff0c;这些阈值被称为显著性水平&#xff08;significance level&#xff0…

CIC滤波器

CIC滤波器结构简单&#xff0c;没有乘法器&#xff0c;只有加法器、积分器和寄存器&#xff0c;适合工作在高抽样率条件下&#xff0c;而且CIC滤波器是一种基于零点相消的FIR滤波器。 CIC滤波器分为单级和多级滤波器。 1.在单极滤波器中&#xff1a; 当CIC滤波器的长度M远大于…

【css3】04-css3转换

目录 1 2D转换 2 3D转换 3 案例&#xff1a;旋转的魔方 1 2D转换 ## 2D转换 ☞ 位移 transform: translate(100px,100px); 备注&#xff1a; 位移是相对元素自身的位置发生位置改变 ☞ 旋转 transform: rotate(60deg); 备注&am…

LabVIEW虚拟测试实验室开发

LabVIEW虚拟测试实验室开发 在当代的科技和工业进步中&#xff0c;测试与测量扮演着至关重要的角色。随着技术的发展&#xff0c;测试系统也变得日益复杂和成本昂贵&#xff0c;同时对测试结果的准确性和测试过程的效率要求越来越高。开发了一种基于LabVIEW的虚拟测试实验室的…

新能源汽车的电驱热管理

前言 新能源汽车的电驱热管理是指维持电动汽车电池、电机和电控系统在适宜的工作温度范围内&#xff0c;保障车辆高效、安全、稳定运行的技术方案。随着新能源汽车的快速发展和普及&#xff0c;电驱热管理技术也日益成为关注焦点。本文将从电池、电机和电控系统三个方面介绍新…

k8s集群的声明式管理资源

一 声明式管理方法 1 适合于对资源的修改操作&#xff08;陈述式方式修改资源非常不方便&#xff09; 2 声明式资源管理方法依赖于yaml资源配置清单文件对资源进行管理 资源配置清单文件有两种格式&#xff1a;yaml&#xff08;人性化&#xff0c;易读&#xff09;&#xff…

中国科学院植物研究所宋献军课题组揭示不同的翻译后修饰协作调控水稻种子大小的新机制

公众号&#xff1a;生信漫谈&#xff0c;获取最新科研信息&#xff01; 中国科学院植物研究所宋献军课题组揭示不同的翻译后修饰协作调控水稻种子大小的新机制https://mp.weixin.qq.com/s/ycNgYzACwkYZbo6k0Zqtcw 未来20年&#xff0c;我国将决战全面建成社会主义现代化国家&…

杰理-耳机进入关机关闭内内置触摸-节省功耗

杰理-耳机进入关机关闭内内置触摸-节省功耗 if (__this->init 0) {return LP_TOUCH_SOFTOFF_MODE_LEGACY; }if ((__this -> softoff_mode LP_TOUCH_SOFTOFF_MODE_ADVANCE) && (__this->softoff_keep 0)) {lp_touch_key_disable(); } __this->softoff_k…

安全设计 | Microsoft 威胁建模工具Threat Modeling Tool安装、使用及威胁生成原理详解(文末附样例)

1. 概览 微软威胁建模工具&#xff08;Threat Modeling Tool&#xff09;是 Microsoft 安全开发生命周期 (SDL&#xff0c;Security Development LifeCycle) 的核心要素。 当潜在安全问题处于无需花费过多成本即可相对容易解决的阶段&#xff0c;软件架构师可以使用威胁建模工…

对vue3/core源码ref.ts文件API的认识过程

对toRef()API的认识的过程: 最开始认识toRef()是从vue3源码中的ref.ts看见的,右侧GPT已经举了例子 然后根据例子,在控制台输出ref对象是什么样子的: 这就是ref对象了,我们根据对象中有没有__v_isRef来判断是不是一个ref对象,当对象存在且__v_isRef true的时候他就判定为是一个…

F28034中断

DSP中断 中断中断概述中断机制 中断 当CPU正在执行程序时&#xff0c;由于发生了某种随机的事件&#xff08;外部或内部&#xff09;&#xff0c;使CPU的执行中断&#xff0c;转而去执行某一段特殊的程序&#xff08;中断子程序或中断处理程序&#xff09;&#xff0c;以处理该…

cs与msf权限传递,以及mimikatz抓取win2012明文密码

目录 解释参数 foreign http foreign https cs与msf权限传递 Cobalt Strike会话传递到Metasploit Framework Cobalt strike上的操作 ​编辑​编辑​编辑 Metasploit Framework上的操作 传递会话 Metasploit Framework会话传递到Cobalt Strike Cobalt strike上的操作…

Tina-Linux -- 3. LVGL测试

参考韦东山 – Tina_Linux_图形系统_开发指南 Tina-linux lvgl 配置 环境配置 进入Tina-SDK根目录 source build/envsetup.sh lunch XXX平台名称 make menuconfigLVGL Gui --->Littlevgl --->< > lv_demo<*> lv_examples &#xff08;lvgl官方demo&#…

监控监测管理系统产品规格说明书(实际原件参考)

【智慧工地】监控监测管理系统产品规格说明书编制模板 一、引言 二、 项目概述 三、 总体需求 四、 功能需求 4.1 概述 4.2 业务功能概要描述 4.3 功能性需求 4.4 功能描述 五、 非功能性需求 5.1 用户界面需求 5.2 软硬件环境需求 5.3 产品质量需求 5.4 接口需求 5.5 其他需求…

HarmonyOS 鸿蒙应用开发 - 多态样式 stateStyles

前言&#xff1a;Styles和Extend仅仅应用于静态页面的样式复用&#xff0c;stateStyles可以依据组件的内部状态的不同&#xff0c;快速设置不同样式&#xff0c;类似于css伪类&#xff0c;但语法不同。 ArkUI提供以下四种状态&#xff1a; focused&#xff1a;获焦态。normal&…

MySQL库/表/数据的操作

文章目录 1.数据库操作1.1 创建、删除、查看和修改1.2 编码格式1.3 备份和恢复 2.表的操作2.1 创建表2.2 存储引擎2.3 查看表、修改表、删除表 3.数据类型3.1整数类型3.2字节类型(bit)3.3浮点类型(bit)3.4 decimal3.5 字符串类型3.6 日期和时间类型3.7 enum和set关于如何查找想…

ES 查询踩坑-全字段匹配

需求&#xff1a;name字段需要全匹配查询 name的映射 普通的must查询 GET power_engin/_search {"from": 0,"size": 10,"query": {"bool": {"must": [{"term": {"name": {"value": "尼…

解决Flutter位于悬浮窗口时,应用Logo不更新问题

问题描述 我已经更换了应用Logo&#xff0c;但是发现应用处于悬浮窗口时&#xff0c;logo还是更改之前的&#xff1f;下面的图片只是示意。 解决方案 终端命令 rm -rf ~/Library/Developer/Xcode/DerivedData2.xcode视图内解决 先在顶部找到 Xcode --> Setting --> Lo…

光速入门python的OpenCV

前言 欢迎来到我的博客 个人主页:北岭敲键盘的荒漠猫-CSDN博客 本文整理python的OpenCV模块的关键知识点 争取用最短的时间入门OpenCV 并且做到笔记功能直接复制使用 OpenCV简介 不浪费时间的介绍: 就是类似于ps操作图片。 至于为什么不直接用ps&#xff0c;因为只有程序能…