HLS-矩阵乘法单元设计与SDK测试

上传人:Baige****0346 文档编号:266122452 上传时间:2022-03-14 格式:DOCX 页数:26 大小:3.06MB
返回 下载 相关 举报
HLS-矩阵乘法单元设计与SDK测试_第1页
第1页 / 共26页
HLS-矩阵乘法单元设计与SDK测试_第2页
第2页 / 共26页
HLS-矩阵乘法单元设计与SDK测试_第3页
第3页 / 共26页
HLS-矩阵乘法单元设计与SDK测试_第4页
第4页 / 共26页
HLS-矩阵乘法单元设计与SDK测试_第5页
第5页 / 共26页
点击查看更多>>
资源描述

《HLS-矩阵乘法单元设计与SDK测试》由会员分享,可在线阅读,更多相关《HLS-矩阵乘法单元设计与SDK测试(26页珍藏版)》请在金锄头文库上搜索。

1、 HLS矩阵乘法单元设计与SDK测试 目录o 一、引言o 二、程序框架o 三、初步设计o 四、报告分析o 五、优化操作o 六、接口优化o 七、上板测试o 八、补充部分o 九、时间与参考一、引言矩阵乘法,涉及数组优化、循环优化和接口优化等。是一个学习HLS非常好的Lab。HLS新建工程这些就不记录了,在新建时有个需要注意,就是Clock Period的设置,如果设为10,会按照100MHz时钟来进行优化,如果一次运算15ms,就会分配到两个时钟来计算。但HLS工具预估是比较保守的,比如预估一次运算15ms,但实际上板卡后这个运算,就只要7ms。因此可以把周期稍微放大些/减轻约束压力,让HLS在做

2、优化时,能放在一个周期内完成,但如果达不到约定的时钟频率,是可以进行更改的。在新建后的工程右键Project Settings,来进行更改。二、程序框架有Source、Include源代码和Test Beach目录。用于实现矩阵乘法功能的代码,放在Source目录下。用于测试矩阵乘法功能的代码,放在Test Beach目录下。新建文件:matrix_mul.cpp、matrix_mul.h和main.cpp。在matrix_mul.h文件中,使用#ifdef 宏的方式,来避免重复声明某些内容。三、初步设计还未进行优化前的基本功能设计。1、matrix_mul.h文件任意精度定点数:在传统C中,

3、char、int、short、long等的位宽都是固定的,8位、32位、16位和64位。如果电路中要求10位宽的数据,则常规变量无法实现,HLS为了能满足需求,搞了一种ap_int类型的数据变量,内放的是该类型变量的位宽,可以认为ap_int A与char B,是两种类型相同的变量。#ifndef _MATRIX_MUL_#define _MATRIX_MUL_/ HLS提供的任意精度定点数文件#include ap_fixed.h/ A元素对应行,与B元素对应列,进行相乘得到Cvoid matrix_mul(ap_int A44, ap_int B44, ap_int C44);#endif

4、2、matrix_mul.cpp文件#include matrix_mul.hvoid matrix_mul(ap_int A44, ap_int B44, ap_int C44)for(int i=0;i4;i+)for(int j=0;j4;j+)Cij=0;/ 循环乘四次,并进行相加for(int k=0;k4;k+)Cij=Cij+Aik*Bkj;3、main.cpp文件#include matrix_mul.h#include int main()ap_int A44;ap_int B44;ap_int C44;/ 初始化赋值0、1、2、3、4、5.for(int i=0;i4;i+

5、)for(int j=0;j4;j+)Aij=i*4+j;Bij=Aij;matrix_mul(A, B, C);for(int i=0;i4;i+)for(int j=0;j4;j+)std:coutCi,j=Cijstd:endl;return 0;代码写完,第一步要跑C Simulation,用快捷键Ctrl + B,就可以进行编译了。生成exe文件,就证明没有语法错误。然后,在菜单栏里,有一个Run C Simulation,点后进行C仿真,来看结果是否正确。是纯C语言的仿真。第二步进行综合,点菜单栏的Run C Synthesis。可能会出现下面这个“The function mus

6、t be specified”错误,原因是可能有很多C函数,但哪个是顶层,需要确定下。在工程中右键Project Settings,选择Synthesis选项卡,将Top Function设置为matrix_mul,就可以跑综合了。四、报告分析综合完,会生成Synthesis的报告文件,下边对该文件的几个关键参数进行分析。1、Performance Estimates,性能估计。1Timing:包含clock,时钟约束。2Latency:在Summary中,包含了Latency与Interval,初步设计中,Latency为169,表示这个矩阵乘法的函数模块,需要耗时169个时钟周期。Inte

7、rval是这次矩阵乘法与下一次,需要间隔多少周期,由于没有进行流水线的设计,这里需要间隔169个时钟周期,才能进行下一个的矩阵运算,因此Interval等于169。在Detail中,有循环内部的一些细节,可以看到每个循环需要的一些周期数,有些循环可能需要状态跳转,会消耗一部分的时钟周期。后续优化,主要也是照着Latency来进行优化。2、Utilization Estimates,资源利用率估计。一些资源使用的情况。3、Interface,端口情况。模块的参数就是端口,可以通过参数来生成不同的接口,不设置为缺省,默认是存储器里的数据。还有一些信号,ap开头,为控制信号。五、优化操作初步设计中,

8、完全没有利用到FPGA的并行性,现考虑一些优化操作,来提高性能。1、行列相乘部分行列相乘后相加的代码,我们希望只用一个周期就计算出来。两个方法,1是利用参数循环展开,2是告诉编译器,这部分编译时,需要1个周期来完成,这样也会自动展开。Cij=0;for(int k=0;k4;k+)Cij=Cij+Aik*Bkj;手动循环展开。在功能模块界面,右边有一个Directive,里边有一个for Statement,点开有三个循环,选中最里边那个子循环,右键Insert Directive,打开Vivado HLS Directive Editor这个界面。选择UNROLL,还有Source File

9、和Directive File的选项,Source File是将参数放在C源代码文件中,Directive File是把参数单独放在一个源代码文件中,一般选择Source File就行了。Note:本来这方式在这里是可以的,但有个Cij=0。如果循环展开的话,这个赋值操作,也会占用一个周期。因此,干脆直接将第二级子循环的Iteration Latency(某个循环消耗的Latency)设置为1,就可以实现上述代码一个周期的目的,如何实现呢?在右边Directive选中第二级循环,右键Insert Directive,打开Vivado HLS Directive Editor后,选择PIPELI

10、NE,将里边的II,就是Iteration Latency,设置为1。操作完,会出现#pragma HLS PIPELINE II=1的命令。该操作可强制让每个运算在一个周期内完成,共16个运算,也就是只需要16个周期。2、数组部分PARTITION单、双口存储器的限制,存储器读写冲突,会出现下图那个错误,导致没法一次读取出4个数据,进行行列相乘。如果把数组A的存储器竖着(二维)切成四个,就可以一次读出四个数据。同理,数组B的存储器横着(一维)切成四个,也可以实现一次读出四个数据。不知道这个原因时,可以先进行仿真,来找到问题的关键。使用#pragma HLS ARRAY_PARTITION v

11、ariable=A complete dim=2来完成切割。3、数组部分RESHAPE将原来深度为16,位宽为8的存储器,变成深度为4,位宽为32的存储器。A数组按二维堆起来,B数组按一维堆起来。使用#pragma HLS ARRAY_RESHAPE variable=A complete dim=2来完成组合。PARTITION一次可以读相同或不同的四个数据地址,但RESHAPE一次读的四个数据,是同一个地址的。通过实验波形,可以更加深入区分这两种操作。all是导出所有信号的波形。至少消耗的时钟周期为16*interval+latency,除此外还有写状态转换的消耗。interval可以被约

12、束为1,那latency呢?latency也可以由#pragma HLS LATENCY min=5 max=5来约束。经过上述操作,综合后可以发现,只用了18个周期便可以完成了,至于为什么不是16个周期,是因为还有一个周期进行启动,并且写操作也有一个周期的延迟。六、接口优化之前使用的都是ap_memory存储器的接口,但模块一般挂接到SoC上,这里将接口改为s_axilite类型,即作为slave设备挂载在SoC上。基本命令是:#pragma HLS INTERFACE s_axilite port=A。实际中发现,如果只添加这个命令,interface接口上,还是有ap_start与ap_

13、done模块使能控制信号,这个需要和axi信号加以区分下,在这里,axi只做了数据传输的工作,但模块需要先使能工作才行,就是通过ap_start来完成的。为了让ap_start和ap_done这些信号也受CPU的控制,可以添加#pragma HLS INTERFACE s_axilite port=return。将ap_start与ap_done都变成axi接口综合后的结果。最后,点击report RTL,就能将工程输出为一个IP,在工程中调用。七、上板测试使用的FPGA型号是xc7z020clg400-1。环境简陋,将就着看。1、平台搭建。创建最小系统的Zynq核,并将DDR、UART0配置

14、好,同时引出100MHz的PL时钟,还有一个复位信号。总线互联模块是一接一的,CPU启动工作matrix_mul模块,通过一个AXI口访问,将16个数据从AXI发送到模块,并检测是否done完成。每次改完,记得生成wapper和generate output两步。2、生成并导出bitstream,同时launch SDK。这个没啥复杂的,传统流程。需要留意下,matrix_mul模块的寄存器地址。3、SDK开发新建一个application project的HelloWorld模板,把串口调通之后,开始进行模块的测试,测试的代码如下。为了看懂这个代码,需要去学习几个AXI外设控制的函数。#include #include platform.h#include xil_printf.h#include stdio.h#include xil_io.h#include xparameters.h#include xmatrix_mul_hw.h#include xmatrix_mul.hint main()int data;int state;/ 如果不使

展开阅读全文
相关资源
相关搜索

当前位置:首页 > IT计算机/网络 > 架构

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号