13_以BNN-PYNQ为例的自定义Overlay分发方法介绍

Python 有非常丰富的第三方库可以使用,很多PYNQ开发者也会在 Github 上提交自己的适用于PYNQ的 Python 包。将一个完成的FPGA工程转换为PYNQ第三方包会方便我们进行PYNQ的开发。这个过程主要包括两个步骤:1.通过已经在PYNQ里的APIs对FPGA部分进行驱动的编写。2.将编写好的驱动做成Python库并且进行打包分发。

从PYNQ框架中可以看到,对于FPGA Bitstreams中的内容,PYNQ有overlays方法对于Bitstream进行类似Vivado中download Bitstream的行为。对于FPGA中其余部分,比如User designs里的内容,可以将它们作为PYNQ的IPs,通过上层的API(如GPIO、MMIO等)对它进行自定义的驱动编写。或者通过其他方法(如:通过python调用C来实现已经在HLS中实现的算法等)。

本节以BNN-PYNQ工程为例,探究在BNN-PYNQ中如何将一个完成的FPGA工程转换为PYNQ第三方包。

首先为第一个步骤,即对FPGA部分进行驱动的编写。在示例的notebook中,首先导入了bnn这个包,在bnn.py这个.py文件中有对bnn的详细描述,其中便包括了对FPGA部分的驱动编写。在bnn.py中,主要包含对三个类的定义:PynqBNN、CnvClassifier、LfcClassifier。其中,PynqBNN主要作为一个共享库加载指定网络并且将bitstream下载到FPGA(PL)中;CnvClassifier是CNV网络的分类器类,用于对cifar10格式的图像和需要预处理的图像进行推理;LfcClassifier是LFC网络的分类器类,用于对mnist格式的图像进行推理。两个类在构造时,都会加载共享库,并且将bitstream下载到FPGA(PL)中。如在CnvClassifier中构造函数的定义:

​ 在CnvClassifier的构造函数中,实例化了一个PynqBNN对象。而在PynqBNN中,构造函数的描述如下:

​ 在PynqBNN的构造函数中,主要部分即为通过os进行文件检索等操作找到bitstream,并且使用Overlay加载它。因此在示例中实例化一个CnvClassifier对象时,PYNQ板卡上的Done信号灯会闪烁(即代表有bitstream加载到PL部分)。

​ 在BNN-PYNQ中,因为网络的相关定义主要通过Vivado HLS进行编写,主要语言对象为C++。因此,项目的核心用法为将C++代码编译为shared library后,python主要作为一个接口对象通过C++共享库与主机库进行通信,具体方法为借助CFFI调用C动态库。如在bnn.py中对CFFI的使用:

在通过源文件编译及在python声明之后,就可以通过python调用c语言定义的函数了,如在PynqBNN中对网络的参数进行读取的函数的定义:

在确认参数文件路径正确之后,会调用之前的声明的C函数load_parameters,用于加载和读取参数。对工程的更多实现方法及内部原理,可以参考项目主页:

https://github.com/Xilinx/BNN-PYNQ

至此,已经简略了解了BNN-PYNQ的基本工作原理和对FPGA进行驱动编写驱动的过程。

在对驱动编写好后,如果要想向 Github仓库提交自己开发的包,首先要将自己的代码打包,才能上传分发。Python 库打包分发的关键在于编写 setup.py 。setup.py是setuptools的构建脚本。它告诉setuptools你的包(例如名称和版本)以及要包含的代码文件。一个简单的setup.py可以编写如下:

可以从实例中看到,setup.py 文件编写的规则是从 setuptools导入 setup 函数,并传入各类参数进行调用。setup函数常用的参数如下:

参数

说明

name

包名称

version

包版本

author

程序的作者

author_email

作者邮箱

url

程序的官网地址 ,对于许多项目这是一个指向GitHub,GitLab,Bitbucket或类似代码托管服务的链接

description

对于程序的简单描述

requires

指定依赖的其他包

packages

需要处理的包目录(通常为包含 init.py 的文件夹),对于复杂的工程,可以使用find_packages()去自动发现所有的包

classifiers

程序的所属分类列表

include_package_data

自动包含包内所有受版本控制(cvs/svn/git)的数据文件

package_data

指定包内需要包含的数据文件

data_files

打包时需要打包的数据文件,如图片,配置文件等

​ 关于setup.py的更多信息,可以参考:

https://packaging.python.org/guides/distributing-packages-using-setuptools/

packages是setup.py中一个重要的参数,它声明了需要处理的包目录。因此在对setup.py进行编写时,需要注意文件的目录结构,BNN的文件目录结构如下图所示:

图5-2 bnn的文件结构

其中,bnn包含了对LfcClassifier和CnvClassifier两个Pyhton类的描述、notebooks中包含了示例notebook,在安装的过程中移到“/home/xilinx/jupyter_notebooks/bnn/”目录下、tests中包含了测试脚本和测试的图片。

BNN的setup.py描述如下(部分核心代码):

在此setup.py中,主要包括了以下参数:name、version、url、license、author、author_email、include_package_data、packages、package_data、data_files、description。

packages中直接指定了包目录,即bnn。

package_data 中指定了包内需要包含的数据文件,包括:'.bit'(bit文件,用于比特流的下载)、'.tcl'(脚本文件,用于解析硬件设计中的ip核信息)、'.bin'(二进制文件,包含网络训练的参数信息)、'.cpp', '.h'(在Vivado HLS中对网络定义时的c++文件和头文件)、'.so'(c进行编译之后的文件,可以借助cffi调用这个动态链接库)。

data_files中指定了包含的数据路径。

在对PYNQ的setup.py编写时,经常会进行板卡环境的检查,即:

通过导入os,可以检查板载的详细信息,当板卡不适配时,可以输出错误信息。

在编写好后setup.py后,就完成了对库的打包过程,这时可以选择上传到代码管理网站如Github后,通过pip和git指令安装:

也可以将BNN包源文件下载到PYNQ后,在根目录中,通过pip指令安装:

Last updated

Was this helpful?