ZYNQ学习之路——SDSoC开发环境介绍

本文转载自:亦梦云烟的博客

本节教程介绍如何使用SDSoC软件创建硬件平台,并且使用它来加速程序函数。

开发环境:

操作系统: windows10 64bit

SDSOC:2018.2

串口: USB-TTL, CP210x

开发板:米尔科技Zturn board(XC7Z010-CLG400)

一、SDSOC IDE开发环境简介

本节介绍如何使用SDx IDE已一个已知的模板创建一个新的工程,标记某个函数使其使用硬件来时现,编译硬件设计并且在开发板上执行。

1.1 创建新的工程
step1. 从桌面的快捷图标启动SDx IDE 2018.2软件。

step2. 以Eclipse为框架的软件都会使用一个目录作为工作空间来保存软件的配置参数以及使用过程中产生的数据。本系列例程以E:/SDx目录作为workspace。

step3. 从SDx IDE的菜单中选择File > New > SDx Project,创建一个新的工程。

图1-1 SDx创建新工程

step4. 点击Next,输入工程名lab1.再点击Next进入选择硬件平台界面。

step5. 在Platform界面选择zc702,点击Next >.

图1-2 选择硬件平台

step6. 在System Configuration配置界面,选择Linux,其他配置可以默认。

图1-3 系统配置

step7. 点击Next.这里会出现一些模板工程,这里包含了可以直接使用的工程源码。

step8. 选择Matrix Multiplication and Addition,点击Finish完成工程的创建。

图1-4 选择矩阵的乘法和加法模板工程

step9. 创建完工程后,软件自动软件了两种编译模式:Debug和Release,当然我们也可以自己创建其他的编译配置,为了获得最好的运行性能,选择Release配置。

a) 使用图标选择编译配置:在软件的菜单栏下点击锤子图标右边的下三角,在展开的菜单中选择2 Release。

图1-5 编译图标

b) 使用右键菜单选择编译配置:在工程名上右键选择Build Configurations > Set Active > 2 Release。

图1-6 右键菜单选择编译配置

c) SDx软件的每个工程都有一个配置窗口,在右上方选择Active build configurations:Release即可。

图1-7 工程配置文件窗口

每一个编译配置都有不同的目标,Debug配置程序编译后生成的ELF可执行文件包含运行时的调试信息,Release配置程序生成一样的可执行文件但不包含调试信息,并且编译器对代码进行而来性能上的优化。

1.2 标记需要硬件实现的函数
本次选择的模板工程包含了两个硬件实现的函数,矩阵乘法(mmult)和矩阵加法(madd)函数。从模板工程创建的工程都已经标记好了需要加速的函数。下面的步骤介绍如何添加和移除需要使用硬件实现加速的函数。

step1. SDx工程的设置窗口有设置工程属性,点击lab1面板,如果没有显示则双击lab1工程中的project.sdx,点击Add Hardware Functions...按钮可以添加函数。

图1-8 添加需要加速的函数

step2. 按住Ctrl同时选择madd和mmult两个函数,点OK可以添加到Hardware functions列表中。

图1-9 添加硬件加速的函数

另外,我们也可展开包含mmult函数的c文件(mmult.cpp),右键选择mmult函数,选择Toggle HW/SW,同时可以看到Hardware Functins中的函数增加或移除了。

1.3 编译硬件加速的设计文件
编译工程生成可执行文件,比特流文件和SD卡启动镜像:

step1. 右键点击工程名,选择Build Project。

SDx IDE将选择的硬件实现函数使用Vivado HLS编译成IP和模块,然后编译综合并将其布局布线到PL中,最后使用ARM GNU编译并连接生成ELF可执行文件。

step2. 在Assistant窗口,双击打开Data Motion Network Report。该报告展示了SDx编译器创建的硬件连接和每个函数的数据传输在硬件中的实现。如下表所示

Partition 0

step3. 打开lab1/Debug/_sds/swstubs/mmult.cpp文件,我们可以看到SDx编译器如何将原来的mmult函数使用新的_p0_mmult_1_noasync函数替代,该函数调用了cf_send_i和cf_wait函数,SDx系统编译器使用这些可重入函数来构建ELF文件去访问硬件函数。

1.4 运行程序
将lab1/Debug/sd_card目录中的所有文件拷贝到SD卡的根目录中,将SD卡插入开发板,上电启动。

连接USB数据线,根据串口号打开终端,再按Reset键重新启动系统,在终端中将出现输出消息。

1.5 小结
本小节简要介绍了如何创建并运行一个使用硬件加速的应用程序,主要需要了解如何设置需要加速的函数以及实现加速的中间过程。

二、性能评估

本节介绍如何估计一个应用程序的性能而不执行整个编译流程。

2.1 设置开发板
调试性能需要进行如下设置步骤:

a) 连接UST-TTL:看Linux系统的输出

b) 连接JTAG仿真器: 下载FPGA的程序

2.2 新建一个用于性能估计的工程
以mmult_pipeline为模板新建一个工程

查看SDx工程的设置,如果窗口没有显示则双击工程下的.sdx后缀的文件。

在Hardware Functions面板mmult_pipeline已经设定为使用硬件实现。

如果HW Functions列表中没有任何函数,可以点击列表右上角闪电图标进行添加。

在工程的设置面板中,在Options一栏中,勾选Estimate performance。

图2-1 勾选Estimate performance

在Assistant窗口中展lab2,右键点击Debug选择编译,编译工程。

编译完成后,生成一个初始化报告,该报告包含一个硬件使用估计总结和一个指向软件运行数据的链接,这可以对比硬件实现与纯软件实现之间的差异,需要注意的是,这里的硬件实现函数并没有真正的再硬件上去运行。

图2-2 性能估计报告

2.3 对比软件和硬件的性能
点击"Click Here"可以下载到开发板中运行查看实际的性能效果,下面是是在XC7Z010中运行的结果:
For graph with functions: mmult_pipeline:main.cpp:94
Estimated hardware latency = 288395
Measured software latency = 1252214
Estimated speedup factor = 4.34201

Estimated speedup factor for top level function 'main' = 1.07624

Estimated resource usage:
dsps used = 10/80
bram used = 24/60
luts used = 13245/17600
FFs used = 17727/35200

可以发现仿真报告与实际的运行结果所使用的资源一致,但运行时间有很大差别,仿真结果显示只加速了1.08倍而实际结果是4.34倍。

2.4 切换加速比较
在加速性能和资源利用估计报表中,总结区显示的是顶层main函数的加速性能,main函数是被设置为默认的,然而,我们通常不想查看诸如分配内存、初始化和设置这一类函数,如果我们想查看其它的函数性能,我们可以特别的指定一个函数作为性能估计,以下步骤是选择硬件加速函数查看新能估计的方法:

1. 在SDx工程的浏览窗口,展开Debug/_sds/est/main.cpp,默认情况下可以看到main函数左上角显示有一个R的标志,这个是作为root函数的标志。

图2-3 root函数查看

2. 在SDx的工程设置窗口中,选择Root function:,浏览选择需要进行性能仿真的函数。

三、代码优化

本节介绍如何修改代码来优化SDx生成的硬件-软件系统,并且根据编译错误修改代码。

3.1 系统端口和DMA简介
在Zynq-7000 SoC系统中,ARM A9处理器有两级内存:片上缓存和外部DDR内存,在可编程逻辑单元侧,SDx IDE创建了DMA模块来使硬件函数可以通过系统的端口直接读写系统内存。

如图3-1所示,PS有三类端口可以将内存传输到PL端:

  • ACP: Accelerator Coherence Port,允许硬件直接访问L2 Cache
  • HPx: 高性能端口,提供直接访问DDR内存或片内内存
  • GPx: 通用功能I/O端口,允许处理器读取硬件的寄存器
  • 当处理器调用一个硬件函数时,它事实上调用了sds++生成的桩函数,将数据通过上述三种端口中的一种,从处理器内存传输到硬件函数在FPGA中实现的内存中。

    图3-1 Zynq 硬件函数实现结构

    下表说明了不同系统端口和他们的特性,sds++编译器会自动的选择最佳的端口来实现数据的传输,但同时也允许用户使用编译选项修改端口的选择。

    3.2 指定系统端口
    双击lab2中的.sdx工程设置文件,可以看到mmult_pipeline函数已经被指定为使用硬件实现。为了获得最高的运行性能,将配置调整为Release模式。

    使用sys_port预编译宏可以指定SDSoC的系统编译器选择使用ACP或者AFI端口来访问处理器的内存。

    1. 此时不必生成SD卡启动镜像,在工程设置中取消勾选Generate SD card image

    2. 右键点击工程选择编译;

    3. 当编译完成后,双击Data Motion Network Report可以查看数据传输网络的报告,最右列包含使用的端口和DMA类型。下图显示了在使用sys_port之前的报告:

    图3-2 使用sys_port之前的数据传输网络报告

    4. 添加sys_port预编译宏:

    i. 双击mmult_accel.h文件,在代码编辑窗口中进行编辑

    ii. 在mmult_pipeline函数的声名之上添加以下宏编译指令

    #pragma SDS data sys_port(in1:ACP, in2:AFI)

    修改后的mmult_accel.h文件内容如下:

    #ifndef MMULT_ACC_H
    #define MMULT_ACC_H

    //Array size to access
    #define DATA_SIZE 32

    #pragma SDS data sys_port(in1:ACP, in2:AFI)
    //Declaring hardware function
    void mmult_pipeline(int in1[DATA_SIZE*DATA_SIZE], int in2[DATA_SIZE*DATA_SIZE] , int out[DATA_SIZE*DATA_SIZE], int dim);

    #endif

    重新编译工程,再次打开Data Motion Network Report文件,显示如下:

    图3-3 使用sys_port之后的数据传输网络报告

    可以看到,in2参数实现为HP0端口传输数据。

    3.3 控制数据传输的选择
    在未指定数据传输方式时,系统编译器自动指定为AXIDMA_SIMPLE,可以使用以下指令来指定数据的传输方式。
    #pragma SDS data data_mover(in1:AXIDMA_SG, in2:AXIDMA_SIMPLE,out:AXIFIFO)

    重新编译工程,再次打开Data Motion Network Report文件,显示如下:

    图3-4 指定数据传输方式

    3.4 使用malloc和sds_alloc
    仍然以上述工程为例,删除上面添加的宏编译指令,将sds_alloc修改为malloc,观察数据传输方式如何从Simple DMA模式变为Scatter-Gather DMA.

    Tips: Scatter-Gather DMA:分散-收集DMA允许一次单一的DMA处理中传输数据到多个内存区域,相当于把多个简单的DMA要求串在一起。

    打开main.cpp文件,将所有的sds_alloc替换为malloc,并且将sds_free替换为free。保存编译工程。

    图3-5 sds_alloc的数据传输

    Tips:

    sds_alloc(size_tsize): 使用连续的地址分配内存;使用AXI_DMA_Simple传输,该协议在连续地址传输上更快。

    malloc:作为自由变量分配在栈。有助于sdsoc编译器选择最佳的数据发;非连续分配内存;使用AXI_DMA_SG传输

    3.5 控制数据传输大小
    打开mmult_accesl.h文件,在需要加速的函数声明上添加指定数据拷贝的指令。

    #define M DATA_SIZE
    #pragma SDS data copy(in1[0:M*M], in2[0:M*M], out[0:M*M])
    #pragma SDS data access_pattern(in1:SEQUENTIAL,in2:SEQUENTIAL,out:SEQUENTIAL)
    //Declaring hardware function
    void mmult_pipeline(int in1[M*M], int in2[M*M] , int out[M*M], int dim);

    重新编译工程,再次打开Data Motion Network Report文件,显示如下:

    图3-6 修改数据传输大小

    3.6 小结
    本节简单的介绍了一些宏编译指令的作用,主要需要知道数据传输过程中使用的硬件端口与指令之间的关系,了解硬件实现方式,下一章详细介绍宏编译指令的使用。

    四、在线调试

    本节介绍如何使用SDx IDE在线调试。

    4.1 调试裸机系统
    调试裸机系统需要准备mini USB数据线连接串口到电脑,发送与接收打印的消息。连接JTAG仿真器。

    step1. 设置调试

    本例程使用前面的mmult_pipeline工程进行调试。

    设置编译为Debug,编译完成后再Assistant中选择工程的Debug,右键单击训责Debug As > Launch on Hardware (SDx Application Debugger).

    图4-1 裸机在线调试界面

    启动调试界面后,程序还未运行,程序运行指针指向main函数的第一个语句,Debug窗口显示程序运行所在的ARM核心,Variables窗口显示当前函数中的变量及其实时的值。

    step2. 运行调试

    点击工具栏中的图标可以进行单步调试、运行、暂停、跳出等操作。

    图4-2 调试工具

    双击代码编辑窗口行号左边可以打断点,运行后到断点处暂停。

    4.2 跟踪裸机系统
    在上述例程的基础上进行操作.

    打开工程配置文件,勾选Enable event tracing.

    图4-3 勾选Enable event tracing

    编译工程,当所有的硬件实现函数被编译为Vivado HLS,并且Vivado IP集成之后,在Console中输出Inserted # hardware monitor cores,该消息说明跟踪特性已经被使能。

    图4-4 插入跟踪信息的编译输出

    编译完成后,右键点击工程,选择Run AS > Trace Application (SDx Application Debugger).

    图4-5 运行跟踪程序

    软件自动下载FPGA程序,ELF程序,并且启动应用程序,然后收集跟踪数据知道应用退出,当程序执行完将显示收集到的数据。

    图4-6 程序跟踪信息

    黄色框中显示了文本描述列表信息,红色框中显示了事件时间轴,它们表示的意义相同。

    需要注意的是,橙色事件代表软件事件,绿色代表加速事件,蓝色代表数据传输事件,点击Show Legend图标可以查看各种颜色所表示的意义。

    五、仿真

    本节介绍如何使用SDx IDE的仿真功能,在SDSoC仿真器中运行程序是一个观察调试数据的好方法,你可以观察操作系统挂起,数据传输的仿真波形。

    首先需要制定需要的操作系统和平台去运行仿真程序,本节将运行调试一个加速的系统。

    NOTE:本例程不必运行在实际的开发板中,所以本例选择ZC702模板进行设计

    step1 创建工程运行仿真

    创建lab5工程,以ZC702平台和Linux操作系统为模板的仿真例程。

    选择菜单File > New >SDx Project,选择Application Project,点击Next输入lab5为工程名,点击Next,选择zc702平台。点击Next,选择操作系统为Linux。

    图5-1 系统配置

    点击Next,选择Emulation Example模板工程,点击Finish完成工程的创建。

    双击打开project.sdx文件,在HW functions面板中mmult_accel已经添加了,如果没有则添加之。

    选择Active build configuration为Debug,在Options的Target下拉菜单中选择Emulation.

    图5-2 选择Target为Emulation

    在选择Emulation之后,其他选择都会变成不可选状态。编译工程。

    step2 启动仿真器

    在菜单栏选择Xilinx > Start/Stop Emulator.

    在弹出的对话框中选择lab5工程,Configuration选择Debug,选择是否显示波形,点击Start启动仿真器。

    图5-3 SDSoC仿真器配置

    如果选择查看波形,Vivado的示波器窗口也会同时打开。

    step3 运行程序

    仿真器将花费一段时间来启动。在右下角的Emulation Console中将启动Linux系统,在qemu%右侧的输入框中可以输入Linux命令,就如同在真的硬件系统中运行。

    在lab5工程上右键选择Debug As > Launch on Emulator(SDx Application Debugger)

    图5-4 在仿真器中调试程序

    程序启动调试之后,调试代码将像在真是的硬件中调试一样,点击运行,挂起等图标执行调试过程。

    最新文章

    最新文章