http://www.tuicool.com/articles/eQ7nEn

最终到了HLS部分。HLS是High Level Synthesis的缩写,是一种能够将高级程序设计语言C,C++。SystemC综合为RTL代码的工具。

生产力的发展推动了设计模式。在电子技术0基础阶段,人们关注的是RLC电路。通过建立微分方程求解电路响应。

门级电路是对RLC的初步封装,人们进而採用布尔代数、卡诺图进行电路设计与分析。之后随着集成电路进一步发展。门电路能够集成为寄存器、触发器、ROM等宏单元。设计工具也变得更为高度模块化。算法级别的电路设计,则一直没有特别好的工具,直到出现了HLS。

HLS能够将算法直接映射为RTL电路,实现了高层次综合。从这个层面上讲,System Generator也是一种高层次综合工具。由于它将matlab算法描写叙述综合为RTL代码。假设今后机器学习、人工智能获得重大突破,也许会出现将人类自然语言综合为RTL代码的工具,不知我们能否见证它的面世。

HLS的学习资源能够參考 http://xilinx.eetrend.com/article/5096 。本节给出较为通用的矩阵与向量相乘样例,从全串行到全并行进行了一步步优化实现。

矩阵实验室Matlab是比較经常使用的数学仿真软件。

本博主用的是R2013a版本号。为了验证矩阵向量相乘正确性。我们先用matlab生成測试矩阵和向量。并利用matlab计算结果。代码例如以下:

  1. clear;
  2. clc;
  3. close all;
  4.  
  5. N = 5;
  6.  
  7. A = randi([1,100],N,N);
  8. b = randi(100,N,1);
  9.  
  10. c = A*b;
  11.  
  12. KKK_SaveToCHeaderFile(A,'A.h');
  13.  
  14. KKK_SaveToCHeaderFile(b,'b.h');
  15. KKK_SaveToCHeaderFile(c,'c.h');

这里给出的是A*b = c的简单样例,A为5X5矩阵。b为5X1向量,结果c为5X1向量。当中KKK_SaveToCHeaderFile()是将矩阵、向量保存为C语言数组的子函数。定义例如以下:

  1. function [] = KKK_SaveToCHeaderFile(var,fn)
  2. fid = fopen(fn,'w');
  3. var = reshape(var.',1,[]);
  4. fprintf(fid,'%d,\r\n',var);
  5. fclose(fid);

给出測试例程中,A例如以下:

  1. 82 10 16 15 66
  2. 91 28 98 43 4
  3. 13 55 96 92 85
  4. 92 96 49 80 94
  5. 64 97 81 96 68
  1. 76
  2. 75
  3. 40
  4. 66
  5. 18

9800 

15846 

16555 

23124 

22939

执行matlab脚本之后,生成三个文件:A.h。b.h。c.h,这些是作为HLS程序的输入数据和參考结果。以下我们用HLS工具实现上述矩阵X向量的功能。第一步,执行Vivado HLS。

选择第一项,Create New Project,建立新projectMatrixMultiply

输入路径和project名之后,点Next。

加入顶层模块文件。这里我们Top Functions输入MatrixMultiply,然后New File...,新建一个.c文件。命名为MatrixMultiply.c(后缀不要省略!

),然后点Next

加入顶层文件測试脚本。这里New一个文件TestMatrixMultiply.c(后缀不要省略!

),然后Add前面用Matlab生成的A.h。b.h,c.h,例如以下图所看到的:

点Next,选择解决方式配置,例如以下图所看到的

其余保持默认,仅仅改动Part Selection部分,改为ZedBoard。

改完后。Finish就可以进入主界面,例如以下图所看到的

能够看出。Vivado HLS界面非常像非常像Xilinx SDK,不同的是前者负责PL部分开发。后者负责PS软件编写。定位不同决定了二者今后的路必定走向分歧。

将MatrixMultiply.c内容改为:

  1. typedef int data_type;
  2. #define N 5
  3.  
  4. void MatrixMultiply(data_type AA[N*N],data_type bb[N],data_type cc[N])
  5. {
  6. int i,j;
  7. for(i = 0;i<N;i++)
  8. {
  9. data_type sum = 0;
  10. for(j = 0;j<N;j++)
  11. {
  12. sum += AA[i*N+j]*bb[j];
  13. }
  14. cc[i] = sum;
  15. }
  16. }

将TestMatrixMultiply.c内容改为:

#include <stdio.h> typedef int data_type; #define N 5

const data_type MatrixA[] = { #include "A.h" }; const data_type Vector_b[] = { #include "b.h" }; const data_type MatlabResult_c[] = { #include "c.h" };

data_type HLS_Result_c[N] = {0}; void CheckResult(data_type * matlab_result,data_type * your_result); int main(void) {  printf("Checking Results:\r\n");  MatrixMultiply(MatrixA,Vector_b,HLS_Result_c);  CheckResult(MatlabResult_c,HLS_Result_c);  return 0; }
void CheckResult(data_type * matlab_result,data_type * your_result) {  int i;  for(i = 0;i<N;i++)  {   printf("Idx %d: Error = %d \r\n",i,matlab_result[i]-your_result[i]);  } }

首先进行C语言仿真验证,点这个button:

结果例如以下:

从C仿真输出看到,仿真结果与matlab计算结果一致,说明我们编写的C程序MatrixMultiply是正确的。

接下来进行综合。按C仿真后面那个三角形button,得到结果例如以下:

注意到,计算延迟为186个时钟周期。

这是未经过优化的版本号,记为版本号1。

为了提高FPGA并行计算性能,我们接下来对它进行优化。

打开MatrixMultiply.c,点Directives页面,能够看到我们能够优化的对象。

注意到矩阵和向量相乘是双层for循环结构。我们先展开最内层for循环,过程例如以下:

右键点击最内側循环,右键,然后Insert Directive...

弹出对话框例如以下,Directives选择UNROLL,OK就可以。后面全部都保持默认。

再次综合后,结果例如以下

可见效果很明显,延迟缩短到51个时钟周期。

用相同方法,展开外层循环。综合后结果例如以下:

计算延迟又减少了1/3。!

但是代价呢?细心的你可能发现占用资源情况发生了较大变化,DSP48E1由最初的4个变为8个后来又成为76个。!

FPGA设计中,延迟的减少,即速度提高,必定会导致面积的增大!

循环展开是优化的一个角度,还有一个角度是从资源出发进行优化。

我们打开Analysis视图。例如以下所看到的:

从分析视图能够看出各个模块的执行顺序,从而为优化提供更为明白的指引。我们发现AA_load导致了延迟,假设全部AA的值都能一次性并行取出,势必会加快计算效率!

回到Synthetic视图,为AA添加Directives:

选择Resources,再点Cores后面的方框,进入Vivado HLS core选择对话框

按上图进行选择。使用ROM是由于在计算矩阵和向量相乘时,AA为常数。确认。

仍然选择AA。添加Directives,例如以下图:

选择数组分解,mode选择全然complete,综合后结果例如以下图:

延迟进一步减少,已经降到11个时钟周期了!。!是否已经达到极限了呢???

答案是否定的。我们进入Analysis视图。看一下还有哪些地方能够优化的。经过对照发现bb也须要分解,于是依照上面的方法对bb进行资源优化,也用ROM-2P类型,也做全分解,再次综合,结果例如以下:

发现延迟进一步减少到8个时钟周期了。。!

老师。能不能再给力点?

能够的!!

我们进入分析视图,发现cc这个回写的步骤堵塞了总体流程,于是我们将cc也进行上述资源优化。仅仅只是资源类型要变为RAM_2P,由于它是须要写入的。

综合结果:

总体延迟已经减少到6个clk周期了!!!

再看Analysis视图:

延迟已经被压缩到极限了。

。。

老师。还能再给力点嘛?

答案是能够的。!

我们前面的全部运算都是基于整形数int,假设将数值精度减少,将大大节省资源。

注意如今DSP48E1须要100个!

看我们怎样将资源再降下来。

这就须要借助“随意精度”数据类型了。

HLS中除了C中定义的char。shrot,int。long。long long 之外。还有随意bit长度的int类型。

我们将代码开头的data_type定义改为:

  1. #include <ap_cint.h>
  2. typedef uint15 data_type;

因为matlab生成的随机数在1~100以内。乘积范围不会超过10000。于是取15bit就能满足要求。

首先验证下结果的正确性,用C Simulation试一下。结果例如以下:

看来结果是正确的(当然也不排除数位不够,溢出后的结果相减也是0,须要你自己决定数值位宽)

综合一下。结果例如以下:

延迟缩短了一半,DSP48E1降低到原来的1/4!!

!!!。!!!!

。!!!

。!

!。!。!!!。。!!!

!!

。。!!。!!

!!

。!

我和我的小伙伴们都震惊了!

!!

。!!!

。!!

。。。!

!!。!

。!!

!!

!!!!。。!

!。!。!

!!!!!

。!!。。

再看Analysis视图

能够发现我们的资源利用率已经达到极致,时序已经压缩到无以复加,实现了全并行计算。系统时钟全然能够达到100MHz。延迟仅3CLK。约30ns,相比matlab。得到约数百倍加速(matlab进行矩阵——向量相乘时採用浮点计算)。

通过本文实验,能够发现利用Vivado HLS实现从最初的C串行实现到全并行实现的步步优化。总结一下优化步骤:

(1)粗优化(循环展开、子函数内联)

(2)訪存优化(块存储分散化、多port存取)

(3)精优化(数值位宽优化、流水线优化)

(4)总线化(利用AXI4、AXI-Stream总线接口,减少总体訪存需求)

利用HLS能够将原来的C算法高速部署到FPGA上,降低直接进行硬件编程的工作量。在非常多情况下,优化手段能够和CUDA进行类比,相互借鉴。CUDA事实上更接近软件接口,而HLS更接近硬件编程接口,也许今后两者会在新的层次上融合为统一架构语言。

ZED-Board从入门到精通系列(八)——Vivado HLS实现FIR滤波器的更多相关文章

  1. Spring Boot从入门到精通(八)日志管理实现和配置信息分析

    Spring Boot对日志的处理,与平时我们处理日志的方式完全一致,它为Java Util Logging.Log4J2和Logback提供了默认配置.对于每种日志都预先配置使用控制台输出和可选的文 ...

  2. ArcGIS10从入门到精通系列实验图文教程(附配套实验数据持续更新)

    @ 目录 1. 专栏简介 2. 专栏地址 3. 专栏目录 1. 专栏简介 本教程<ArcGIS从入门到精通系列实验教程>内容包括:ArcGIS平台简介.ArcGIS应用基础.空间数据的采集 ...

  3. redis入门到精通系列(四):Jedis--使用java操作redis详解

    (一)前言 如果不把数据库和后端语言联系起来,就起不到数据库应该要起到的作用.Java语言通过JDBC操作mysql,用Jedis操作redis.当然了,java操作redis的方式不止jedis一种 ...

  4. Provisioning Services 7.6 入门到精通系列之一:PVS前期规划

    1.  Provisioning Services 产品概述 Provisioning Services (简称PVS)采用了一种与传统映像解决方案截然不同的方法,从根本上改变了硬件与依托硬件而运行的 ...

  5. Jenkins pipeline 入门到精通系列文章

    Jenkins2 入门到精通系列文章. Jenkins2 下载与启动jenkins2 插件安装jenkins2 hellopipelinejenkins2 pipeline介绍jenkins2 jav ...

  6. 办公软件Office PPT 2010视频教程从入门到精通系列教程(22课时)

    办公软件Office PPT 2010视频教程从入门到精通系列教程(22课时) 乔布斯的成功离不开美轮美奂的幻灯片效果,一个成功的商务人士.部门经理也少不了各种各样的PPT幻灯片.绿色资源网给你提供了 ...

  7. NHibernate从入门到精通系列

    http://www.cnblogs.com/GoodHelper/archive/2011/02/17/1948744.html NHibernate从入门到精通系列(4)——持久对象的生命周期(上 ...

  8. Selenium 入门到精通系列:六

    Selenium 入门到精通系列 PS:Checkbox方法 例子 HTML: <html> <head> <title>测试页面</title> &l ...

  9. Selenium 入门到精通系列:五

    Selenium 入门到精通系列 PS:显式等待.隐式等待.强制等待方法 例子 #!/usr/bin/env python # -*- coding: utf-8 -*- # @Date : 2019 ...

随机推荐

  1. G彩娱乐网【分享】想要开源自己的代码可以参考一下

    作为一个开发者,如果你打算开源自己的代码,千万不要忘记,选择一种开源许可证(license). 许多开发者对开源许可证了解很少,不清楚有哪些许可证,应该怎么选择.本文介绍开源许可证的基本知识,主要参考 ...

  2. Lambda转sql部分代码保存

    public class SqlExpressionTree { public string GetQuerySql<T>(Expression<Func<T, bool> ...

  3. GCC 中的编译器堆栈保护技术

    GCC 中的编译器堆栈保护技术 前几天看到的觉得不错得博客于是转发了,但这里我补充一下一些点. GCC通过栈保护选项-fstack-protector-all编译时额外添加两个符号,__stack_c ...

  4. ASP.NET Core 与 Vue.js 服务端渲染

    http://mgyongyosi.com/2016/Vuejs-server-side-rendering-with-aspnet-core/ 原作者:Mihály Gyöngyösi 译者:oop ...

  5. C:\WINDOWS\system32\wmp.dll”受到“Windows 系统文件保护”

    在VC# 2005 中,要是打包的程序中包含了Windows Media Player 这个组件的话,在生成解决方案的过程中会提示出错:  "错误1,应将“wmp.dll”排除,原因是其源文 ...

  6. 【python】python的正则表达式 re

    ps:本文摘自互联网,觉得结构很好,讲的也很清晰.记下,备查. 延伸阅读:python的 内建函数 和 subprocess .此文是本系列的第三篇文章了,和之前一样,内容出自官方文档,但是会有自己的 ...

  7. ubuntu-16.04使用MDK3伪造wifi热点和攻击wifi热点至死

    MDK3是? MDK3 是一款无线DOS 攻击测试工具,能够发起Beacon Flood.Authentication DoS.Deauthentication/Disassociation Amok ...

  8. 2)C语言的基本知识(C自考学习)

    字符集 在C语言程序中允许出现的所有基本字符的组合称为C语言的字符集.C语言的字符集就是ASCII字符集.主要包含一下几类: 1)大小写英文字母A~Z,a~z(52个) 2)数字0-9(10个) 3) ...

  9. iOS swift的xcworkspace多项目管理(架构思想)

    iOS  swift的xcworkspace多项目管理(架构思想) 技术说明: 今天在这里分享 swift下的 xcworkspace多项目管理(架构思想),能为我们在开发中带来哪些便捷?能为我们对整 ...

  10. P2757 导弹的召唤(数据加强)

    传送门 LIS的O(nlgn)模板题.加强"导弹拦截" #include <cstdio> #include <cstring> #include < ...