本文档系列是我在实践将神经网络实现到Xilinx 的zynq的FPGA上遇到的问题和解决方法。
目标:本文档重点探讨vivado HLS软件的使用,描述如何将相应的c程序用HLS转换为硬件可以实现的IPcore。
完成本过程可以参阅的文档有:
UG902:Vivado Design Suite User Guide: High-Level Synthesis
该文档主要涉及vivado HLS的理解,vivado HLS软件的初步使用,以及相应的HLS相关的c语言库等,我们主要关注该文档的第一章:用vivado HLS软件实现HLS(高层综合High-level Synthesis)
UG871:Vivado Desigh Suite Tutoril:High-level Synthesis
该文档主要涉及vivado HLS软件的具体操作过程,包括HLS的介绍、c的验证、管脚综合、任意精度数、设计分析、优化分析、RTL验证、用HLS生成集成IP、在Zynq的AP Soc设计中用HLS生成的IP、这个文档是操作的重点。文档中有较多设计实例可以参考。
一、二、三为软件用法和具体操作步骤,四、为我们实现我们的代码需要完成的工作。
一、打开及创建工程
打开软件,creat project这些基础的操作就不讲了。我们的版本是vivado HLS 2016.4
相应的LeNet-5的源码去github上下载,注意需要是c或者c++版本的代码。运行前务必看懂其中的代码,至少知道每个函数的意思和调用关系,这样后面操作才会顺畅。(HLS只可以synthesis部分的c和c++程序,所以有部分源码不可用,这个是后面讨论的内容。)
1.1. 下面我们就打开软件,create new project,输入相应的工程名和工程位置。
1.2. 把相应的文件添加到对应位置。注意一个加入的是source file,意思是用于进行HLS综合的源c代码,另一个加入的是testbench,就是用于测试和后续验证的c语言代码和相应的数据。
top function意思是进行synthesis的c的最高级别的函数。
1.3. 创建solution,period是时钟周期,默认10ns,旁边uncertainty为时钟不确定性,点part selection
因为我们用的是Xilinx zynq 7z035和7z020的测试板,为具体的每个板子的型号。点击finish就进入下面界面。
把面板中各个部分和相应的按钮熟悉一下。一会会在操作中用到这里的按钮,不要找不到对应的命令按钮。
二、进行相应的synthesis
可以按照UG902文档中Chapter1的流程把相应的例程运行一遍。该例子按顺序实现了管理端口接口、优化设计、进行RTL验证、输出RTL设计。为c到RTL语言的全部流程。
这里我们只运用涉及我们项目进行到的操作。synthesis步骤之中只需要进行一步,就是加入derective优化之后进行c synthesis,其他步骤只是为了验证和debug程序用的。
2.1. 将程序添加到相应的目录
把面板中各个部分和相应的按钮熟悉一下。一会会在操作中用到这里的按钮,不要找不到对应的命令按钮。
二、进行相应的synthesis
可以按照UG902文档中Chapter1的流程把相应的例程运行一遍。该例子按顺序实现了管理端口接口、优化设计、进行RTL验证、输出RTL设计。为c到RTL语言的全部流程。
这里我们只运用涉及我们项目进行到的操作。synthesis步骤之中只需要进行一步,就是加入derective优化之后进行c synthesis,其他步骤只是为了验证和debug程序用的。
2.1. 将程序添加到相应的目录
注意source中为子程序,test bench中为测试的程序和需要读入的东西。
2.2. 我们先进行相应的仿真验证,上面图1-8中的operation中的点击c simulation,进行c语言的仿真,会发现程序正常运行。
2.3. 但是在进行C/RTL cosimulation(非必要步骤)的时候,出现了一定的问题
ERROR: [SYNCHK 200-61] src/top.cpp:49: unsupported memory access on variable 'sample' which is (or contains) an array with unknown size at compile time.
ERROR: [HLS 200-70] Synthesizability check failed.
command 'ap_source' returned error code
while executing
我们可以发现问题的所在,用于c与RTL协同synthesis中的top.cpp中的neural中的一个sample的指针,在c编译的时候可以用指针,但是vivado HLS并不知道这个sample的大小,因此不知道如何在板子中给sample分配内存,因此synthesis失败了。同时,另一个问题可能与ap_source有关。
我们所以要解决这个问题,必须搞明白数组是如何在FPGA中存储的。同时搞明白ap_source是个什么。
2.4. 在进行搞明白相应的存储以及ap_source之前,我们尝试在程序中下手解决这个问题,首先在top.h中把top.h中加入#define N 480,然后把1830行的声明去掉nerual(float *sample, unsigned int *result),top.cpp中也去掉输入的参数int N。
程序synthesis了很久,没有像第一次那样快速的报错。
为了避免重复的操作耗费时间,我们将程序中的sample加入axi4总线。然后在几个主要的底层的for循环之中运用PIPELINE。(不知这个步骤对于缩减运行时间而言有用与否。并且具体的优化比较繁杂,后面再看)
终于完成了c的synthesis。完成synthesis之后,会生成一个相应的报告,大致涉及运用的资源以及时钟周期,我们先不管报告内容,那是后面优化所需要做的内容(优化相关知识在UG902 中的Optimizing the design中)。我们先继续往下运行,把流程先跑通。
2.5. 点击C/RTL cosimulation(非必要步骤),进行c与RTL的协同综合(UG902中Verifying the RTL)。运行依然非常慢。(但是此步骤可以略过,完成输出RTL此步骤并非必须的)
运行一晚上之后进展缓慢,我们可以重新开始一下试一下。
第一次勾选的是VHDL,并且没有勾选optimizing compile选项,运行一整晚卡在一个地方。现在我们运行verilog,并且勾选Optimizing compile选项。
以下选项含义(UG902 Using C/RTL co-simulation):
Setup Only: 只创建所需要的文档(wrappers, adapters, and scripts),只运行simulation但不执行simulator,要想执行在RTL文件夹下
Dump Trace:会生成一个trace 文档,在
Optimizing Compile:会增加compile的时间,但是simulation会执行的更快
Reduce Disk Space:TRL simulation会产生大量数据,此步可以把分成N个分开的RTL仿真,但是会运行变慢。
Compiled Library Location:确定compiled library的位置,以便于用第三方的RTL simulatior
Input Arguments:为test bench确定任何输入的arugments
这次没有像上次一样卡在一个地方不动,但是RTL仿真时十分慢,运行了两天左右达到了这个进度,并且进度大于100%,为了解决这个问题我们需要查阅文档找出原因。
在运行了三天之后,我们停止了此过程,此时已经可以进行export RTL,(其实在进行synthesis之后就能export RTL了)
三、输出RTL为IPcore
点击export RTL,输出RTL成功表明生成IP core成功,我们在后续的工作中可以通过vivado验证这一点。
在进行完这些步骤后,我们大致可以认为已经可以将c语言通过vivado HLS转化为相应的硬件RTL语言,下面我们就开始进行相应的系统设计。
四、实现cnn主程序编译为IPcore
1.创建工程,添加源码这些就不说了,我们需要给两个参数加入相应Interface的axi总线协议,这样才能通过单片机与相应的IPcore实现传递数据。
要给相应的输入输出流加axis总线协议。这样生成的IPcore的才有两个接口,不然生成的IPcore接口有很多。例如下图为一个典型的错误的IPcore
2.点击c synthesis,之后点击export RTL,就把相应的IPcore保存在了对应的solution目录里面了。
生成的IP为XCI文件,能被加入到project之中。
---------------------
作者:邢翔瑞
来源:CSDN
原文:https://blog.csdn.net/weixin_36474809/article/details/80597166