×
嵌入式 > 嵌入式开发 > 详情

手把手教你在FPGA实例上运行“Hello World”

发布时间:2020-07-06 发布时间:
|

前言

在4月19号的旧金山AWS技术峰会上,亚马逊CTOWernerVogels宣布了多项AWS新功能,其中就包括众人期待已久的FPGA实例F1。

F1实例配有最新的16nmXilinxUltraScalePlusFPGA,目前有f1.2xlarge和f1.16xlarge两种类型,其中f1.2xlarge配备有1个FPGA卡,f1.16xlarge配备有8个FPGA卡。

使用F1实例部署硬件加速在许多高性能计算(HPC)应用程序中非常有用,可解决需要高带宽、增强型联网和较高计算能力的复杂科学、工程和业务问题。F1实例尤其适用于有时间要求的应用程序,如临床基因组学、实时视频处理和财务风险分析。

因为这段时间都在学习神经网络,所以F1实例最吸引我的是在FPGA上部署神经网络模型,神经网络的前向计算以高频脉冲的方式同时发生在门电路构成的神经网络单元上,想想都让人激动。

不过FPGA这个东西确实太专业了,入门学习曲线不是一般的陡,启动F1实例运行一个简单的HelloWorld都需要折腾一番。

所以在这里记录一下自己启动F1实例运行HelloWorld的过程,供各位参考,希望可以让大家开始开始FPGA的旅程。

启动f1实例

f1实例的启动过程和一般的EC2启动过程类似,有关AWS账号的准备,EC2创建过程的细节请大家参考相关技术文档。以下只列出一些需要注意的地方。

测试时我选择了“弗吉尼亚北部”这个区域,也就是us-east-1区域。

启动f1实例时强烈推荐使用AWSFPGADeveloperAMI镜像,FPGADeveloperAMI包括一个预先打包的工具开发环境,其中含有用于模拟FPGA设计、编译代码及构建和注册AFI的脚本和工具。

在启动实例的第一步,选择系统镜像的时候选择“AWSMarketplace”,然后搜索“FPGA”就可以找到FPGADeveloperAMI,该镜像在弗吉尼亚北部区域的ID为:ami-3afc6f2c,镜像选择界面截图如下。

启动过程中注意给你的实例指定一个IAMRole,后续使用AWSCLI命令行工具的时候就需要配置静态的AccessKey和SecretKey了。

还有就是安全组配置,缺省的22号端口保留打开状态,另外建议开3389端口,后续如果你希望使用远程连接的方式使用图形化界面需要用到这个端口。

还有一个不需要再强调的就是你启动的f1实例需要有公有IP。

系统登录

在f1实例启动后在EC2控制台上找到这台实例的公有IP地址,然后通过ssh命令连接该实例,注意使用的用户名是centos,ssh命令样例如下:

ssh-i~/.ssh/centos@

登录以后可以看到下面的信息:

____________________________

|__|_/__|/_||__///_|/|__|

|_||_/(_|/_||)|_|V//_||/||||

|_||_|___/_/_|___/|___|_//_/__||_|___|

AMIVersion:1.2.0

Readme:/home/centos/src/README.md

GUISetupSteps:/home/centos/src/GUI_README.md

AMIReleaseNotes:/home/centos/src/RELEASE_NOTES.md

XilinxTools:/opt/Xilinx/

DeveloperSupport:/zixunimg/eepwimg/github.com/aws/aws-fpga/blob/master/README.md#developer-support

注意这里提到的GUI设置说明文档:/home/centos/src/GUI_README.md,如果你后续希望使用图形化界面,请参考这个文档进行操作。

克隆AWSFPGA项目

在远程f1实例上创建一个工作目录,在该工作目录下执行以下命令克隆AWSFPGA项目:

gitclone/zixunimg/eepwimg/github.com/aws/aws-fpga.git

执行完成以后可以看到一个aws-fpga目录

安装FPGASDK

进入aws-fpga目录,然后执行以下命令安装FPGASDK:

sourcesdk_setup.sh

安装命令执行完以后会有以下输出,表示安装成功:

DonewithSDKinstall.

DonewithAWSSDKsetup.

这个过程会安装好FPGA管理工具,通过这个管理工具可以查看FPGA卡的情况,列出FPGA卡上的镜像情况,还可以执行加载镜像等操作。

首先我们可以通过fpga-describe-local-image-slots命令查看FPGA卡的情况,这里就是FPGA的“imageslot”的情况,具体命令请如下:

sudofpga-describe-local-image-slots-H

在我的f1.2xlarge实例上有如下输出:

$sudofpga-describe-local-image-slots-H

TypeFpgaImageSlotVendorIdDeviceIdDBDF

AFIDEVICE00x1d0f0x10420000:00:1d.0

这里列出的就是slot0的情况,接着你可以使用fpga-describe-local-image-slots命令查看这个slot上的FPGA镜像情况:

sudofpga-describe-local-image-S0

其中参数-S用于指定希望查看的imageslot,参数值就是FPGAimageslot的编号。

如果你希望将新的FPGA镜像加载到一个imageslot上,你可以使用命令fpga-load-local-image,同时通过参数-S指定imageslot的编号,通过-I参数指定需要加载的FPGA镜像ID,如:

sudofpga-load-local-image-S0-Iagfi-0123456789abcdefg

有关FPGA管理工具的更多信息,请参考以下链接:

/zixunimg/eepwimg/github.com/aws/aws-fpga/blob/master/sdk/userspace/fpga_mgmt_tool...

安装FPGAHDK

安装好FPGA的SDK以后就需要安装FPGAHDK了,具体的安装命令如下:

sourcehdk_setup.sh

这个过程稍长一点,可能需要5到10分钟,执行的命令的时候输出结果中也有提示:

AWSFPGA-INFO:Thiscouldtake5-10minutes,pleasebepatient!

如果一切正常,安装成功后会有如下信息:

AWSFPGA-INFO:DDR4modelbuildpassed.

AWSFPGA-INFO:ATTENTION:Don'tforgettosettheCL_DIRvariableforthedirectoryofyourCustomLogic.

AWSFPGA-INFO:AWSHDKsetupPASSED.

如成功信息里提示的,如果你以后要构建自己的FPGA模块,需要将CL_DIR变量指向你的模块目录,我们在后续的步骤中会进行设置。

配置AWSCLI

因为FPGA镜像创建过程需要使用AWSCLI命令行工具,所以我们需要提前配置好AWSCLI。

在我们使用的这个FPGADeveloperAMI中AWSCLI命令行工具已经安装好了,如果你使用其它镜像需要手工安装AWSCLI的话请参考AWSCLI命令行工具的安装文档。

需要注意的时,虽然在FPGADeveloperAMI中已经安装好了AWSCLI,但是这个版本不一定是最新的,所以建议通过以下命令先进行升级:

pipinstall--upgrade--userawscli

然后就通过以下命令启动AWSCLI配置过程:

awsconfigure

在配置AWSCLI的过程中一般需要提供AccessKey和SecretKey,不过我们的f1实例在启动过程中制定了IAMRole,而且我给这个IAMRole足够的权限,所以我们这里不需要配置静态的AccessKey和SecretKey,我们要做的只是指定区域,这里我们指定区域为us-east-1。

$awsconfigure

AWSAccessKeyID[None]:

AWSSecretAccessKey[None]:

Defaultregionname[None]:us-east-1

Defaultoutputformat[None]:

构建DCP

安装好HDK,配置好工具,就可以开始跑样例了,这里我们使用AWSFPGA项目里的helloworld样例,该样例在aws-fpga中的以下目录中:

./hdk/cl/examples/cl_hello_world

如之前安装过程中提到的,如果我们使用目录./hdk/cl/examples/cl_hello_world中的样例,我们需要设置CL_DIR变量指向./hdk/cl/examples/cl_hello_world目录,具体命令如下:

cd./hdk/cl/examples/cl_hello_world

exportCL_DIR=$(pwd)

接下来的工作需要使用XilinxVivado工具,所以我们需要检查一下vivado工具是否安装正常,具体命令如下:

$vivado-modebatch

正常的输出如下:

******Vivadov2017.1(64-bit)

****SWBuild1846317onFriApr1418:54:47MDT2017

****IPBuild1846188onFriApr1420:52:08MDT2017

**Copyright1986-2017Xilinx,Inc.AllRightsReserved.

Sourcingtclscript'/opt/Xilinx/Vivado/2017.1/scripts/Vivado_init.tcl'

INFO:[Common17-206]ExitingVivadoatFriApr2102:42:352017...

现在我们可以开始构建DCP了,构建命令在$CL_DIR/build/scripts中,文件名是aws_build_dcp_from_cl.sh,所以具体命令如下:

cd$CL_DIR/build/scripts

$./aws_build_dcp_from_cl.sh

需要注意的是,这个命令的运行时间比较长,需要几个小时的时间才能完成。为了避免ssh会话中断导致构建失败,样例的作者选择在后台运行建构过程。在我们运行aws_build_dcp_from_cl.sh命令之后,会马上获得以下输出,不过构建程序会在后台持续运行:

$./aws_build_dcp_from_cl.sh

AWSFPGA:Startingthedesigncheckpointbuildprocess

AWSFPGA:Checkingforproperenvironmentvariablesandbuilddirectories

Creatingthereportsdirectory

Creatingthecheckpointssdirectory

Creatingthecheckpoints/to_awsdirectory

AWSFPGA:Environmentvariablesanddirectoriesarepresent.CheckingforVivadoinstallation.

AWSFPGA:BuildthroughVivadoisrunningasbackgroundprocess,thismaytakefewhours.

AWSFPGA:Outputisbeingredirectedto17_04_21-025018.nohup.out

AWSFPGA:IfyouhavesetyourEMAILenvironmentvariableand-notifyisspecified,youwillreceiveanotificationwhencomplete.

AWSFPGA:(See$HDK_DIR/cl/examples/README.mdfordetails)

在以上输出中我们可以注意到,构建日志会输出到文件xxxx.nohup.out中,所以我们可以定时查看这个日志文件从而了解构建进程.

当然,时不时跑过来看看日志文件看看是不是构建完成了并不是一个很有效的办法,如果你希望构建程序在结束的时候给你发一封邮件,可以使用-notify参数,使用-notify参数前需要通过以下命令设置SNS:

$exportEMAIL=your.email@example.com

$./$HDK_COMMON_DIR/scripts/notify_via_sns.py

有关-notify参数的更多信息请参考对应的READMD.md文件,本例中就不设置了,采用定时查看日志的笨办法。

在构建结束后,我们可以在xxxx.nohup.out文件中看到以下信息:

AWSFPGA:(07:00:53)Finishedcreatingfinaltarfileinto_awsdirectory.

然后你可以查看一下这个目录:$CL_DIR/build/checkpoints/to_aws,目录中会有打包好的tar文件,执行ls命令的结果如下:

$lscheckpoints/to_aws

17_04_21-025018.Developer_CL.tar17_04_21-025018.manifest.txt17_04_21-025018.SH_CL_routed.dcp

上传文件到S3

在构建的dcp以后,我们需要将tar文件上传到S3上,然后才能通过AWSCLI命令构建FPGAimage。

为了上传文件到S3上,我们需要创建对应的S3桶,这个过程可以通过AWS控制台完成,也可以使用AWSCLI命令行工具完成,有关S3的具体操作请参考相关文档。

本例使用AWSCLI来创建S3桶并上传文件,命令参考如下:

$awss3mbs3://--regionus-east-1

$awss3cp$CL_DIR/build/checkpoints/to_aws/*.Developer_CL.tars3:////

接着我们还需要为日志文件创建一个目录,其实在S3上没有目录的概念,整个文件路径和文件名就是这个文件的key,所以样例中创建目录的方法就是直接上传一个空文件到我们需要的目录中,具体命令如下:

$touchLOGS_FILES_GO_HERE.txt

$awss3cpLOGS_FILES_GO_HERE.txts3:////

因为我们上传的tar文件最后会交由AWS对应账号完成构建工作,同时构建日志还需要由AWS对应账号写回到我们的S3桶中,所以我们需要为我们的S3桶设置桶访问策略,让AWS账号可以访问这些文件和目录。具体的访问策略样例如下,我们需要把下面的策略配置拷贝到我们的S3桶的“访问策略”设置中。注意样例中的和等内容,要把它们修改成真实的桶名和对应路径。

{

"Version":"2012-10-17",

"Statement":[

{

"Sid":"Bucketlevelpermissions",

"Effect":"Allow",

"Principal":{

"AWS":"arn:aws:iam::365015490807:root"

},

"Action":[

"s3:ListBucket"

],

"Resource":"arn:aws:s3:::"

},

{

"Sid":"Objectreadpermissions",

"Effect":"Allow",

"Principal":{

"AWS":"arn:aws:iam::365015490807:root"

},

"Action":[

"s3:GetObject"

],

"Resource":"arn:aws:s3::://"

},

{

"Sid":"Folderwritepermissions",

"Effect":"Allow",

"Principal":{

"AWS":"arn:aws:iam::365015490807:root"

},

"Action":[

"s3:PutObject"

],

"Resource":"arn:aws:s3::://*"

}

]

}

设置完S3的桶访问策略以后我们需要验证一下策略写的对不对,不然策略写错了,AWS对应账号拿不到需要的tar文件,就不能成功构建FPGAimage了,而且我们分析问题还不知道如何下手。

验证S3桶策略的脚本在下面这个文件里:

`aws-fpga/hdk/common/scripts/check_s3_bucket_policy.py`

如果执行出现INFO:Passed字样就表示策略设置正确。

不过在有些python环境下check_s3_bucket_policy.py运行会报下面这个错误:

AttributeError:PolicyStatementinstancehasnoattribute'principals_re'

发现这个错误的话需要手工改一下check_s3_bucket_policy.py文件。

用你习惯的编辑器打开文件check_s3_bucket_policy.py,然后找到下面的代码:

classPolicyStatement:

def__init__(self,statement,principal=None):

self.statement=statement

self.process_policy_statement(statement,principal)

self.principals_re=[]

self.actions_re=[]

self.notactions_re=[]

self.resources_re=[]

然后把self.process_policy_statement(statement,principal)这句放到其它变量设置之后,像下面这样:

classPolicyStatement:

def__init__(self,statement,principal=None):

self.statement=statement

self.principals_re=[]

self.actions_re=[]

self.notactions_re=[]

self.resources_re=[]

self.process_policy_statement(statement,principal)

然后就不会报错了,具体运行check_s3_bucket_policy.py命令的参考和对应输出如下:

$check_s3_bucket_policy.py--dcp-bucketfpga.use1.damondeng.com--dcp-keyfpgajarfile/17_04_21-025018.Developer_CL.tar

--logs-bucketfpga.use1.damondeng.com--logs-keylogfile

INFO:Passed

一切准备好就可以开始运行awsec2create-fpga-image命令构建FPGAimage了,命令参考如下:

$awsec2create-fpga-image--nameDamonFPGAOne

--description"TestingFPGAImage"--input-storage-locationBucket=fpga.use1.damondeng.com,Key=fpgajarfile/17_04_21-025018.Developer_CL.tar

--logs-storage-locationBucket=fpga.use1.damondeng.com,Key=logfile

如果你发现AWSCLI命令报下面这个错误,则你的AWSCLI版本不够,需要运行pipinstall--upgrade--userawscli进行升级:

Invalidchoice:'create-fpga-image',maybeyoumeant:

*create-image

*

运行正常的情况下你会获得类似这样的输出:

{

"FpgaImageId":"afi-046ead8eb3a0e3112",

"FpgaImageGlobalId":"agfi-06fdb0f3cea076195"

}

其中”FpgaImageId”是本区域唯一的imageID,”FpgaImageGlobalId”是全球唯一的imageID,后面我们加载FPGAimage时要使用过的是全球唯一的”FpgaImageGlobalId”,以agfi开头。

开始构建FPGAimage后需要等待一段时间,你可以查看你指定的保存日志的S3桶以了解进展。

如果你在日志目录里看到有个新目录产生,里面有个叫State的文件中出现{State=available}字样就表明构建成功了。接着就可以加载你的FPGAimage了。

在加载新的FPGAimage之前记得先清除现有image:

sudofpga-clear-local-image-S0

接着通过以下命令加载FPGAimage:

sudofpga-load-local-image-S0-Iagfi-06fdb0f3cea076195

如之前描述的,这里-S参数用于指定imageslot,-I参数用于指定FPGAimage的镜像ID,注意是全球唯一,以agfi开头的镜像ID。

为了检查FPGAimage是否加载成功,可以使用fpga-describe-local-image命令,执行输出的样例如下:

$sudofpga-describe-local-image-S0-R-H

TypeFpgaImageSlotFpgaImageIdStatusNameStatusCodeErrorNameErrorCodeShVersion

AFI0agfi-06fdb0f3cea076195loaded0ok00x04151701

TypeFpgaImageSlotVendorIdDeviceIdDBDF

AFIDEVICE00x1d0f0xf0000000:00:1d.0

其中可以看到镜像ID为agfi-06fdb0f3cea076195的状态是loaded,就是加载成功了。

最后我们就需要运行宿主机上的软件端来测试了,进入cd$CL_DIR/software/runtime/目录,这里有个写好的c的代码用于测试,运行以下命令编译软件测试端:

$cd$CL_DIR/software/runtime/

$makeall

编译成功后通过./test_hello_world命令执行,以下是执行结果:

$sudo./test_hello_world

AFIPCIVendorID:0x1d0f,DeviceID0xf000

=====Startingwithpeek_poke_example=====

register:0xdeadbeef

Resultingvaluematchedexpectedvalue0xdeadbeef.Itworked!

DevelopersareencourgedtomodifytheVirtualDIPSwitchbycallingthelinuxshell

commandtodemonstratehowAWSFPGAVirtualDIPswitchescanbeusedtochangeaCustomLogicfunctionality:

$fpga-set-virtual-dip-switch-S(slot-id)-D(16digitsetting)

Inthisexample,settingavirtualDIPswitchtozeroclearsthecorrespondingLED,evenifthepeek-pokeexamplewouldsetitto1.

Forinstance:

#fpga-set-virtual-dip-switch-S0-D1111111111111111

#fpga-get-virtual-led-S0

FPGAslotid0havethefollowingVirtualLED:

1010-1101-1101-1110

#fpga-set-virtual-dip-switch-S0-D0000000000000000

#fpga-get-virtual-led-S0

FPGAslotid0havethefollowingVirtualLED:

0000-0000-0000-0000

这个样例有两部分,一部分是peek_poke部分,就是寄存器的读写。样例为了说明FPGA寄存器的功能是否起作用,将输入的比特位做了交换。

如./test_hello_world.c中的代码所描述的:

uint32_tvalue=0xefbeadde;

uint32_texpected=0xdeadbeef;

/*readitbackandprintitout;youshouldexpectthebyteordertobe

*reversed(That'swhatthisCLdoes)*/

第二个部分是虚拟LED的使用,测试者可以通过FPGA管理工具设置virtual-dip开关,以类似掩码的形式影响虚拟LED的显示,比如,原来虚拟LED的输出是1010-1101-1101-1110我通过fpga-set-virtual-dip-switch设置了1111111100000000值,虚拟LED的输出就是1010-1101-0000-0000:

[centos@ip-172-31-8-87runtime]$sudofpga-set-virtual-dip-switch-S0-D1111111100000000

[centos@ip-172-31-8-87runtime]$sudofpga-get-virtual-led-S0

FPGAslotid0havethefollowingVirtualLED:

1010-1101-0000-0000

到这里我们的HelloWorld就成功啦,虽然比一搬的软件HelloWorld麻烦好多,但是要知道这里可是直接操控硬件喔。

后续工作

在跑完HelloWorld样例以后可能会有不少人想了解这个开发环境的图形化访问的问题。

如文中提到的,当你通过SSH登录到FPGA实例时,FPGADeveloperAMI的欢迎文字中有提到GUI界面的设置。这里提到的方法概括起来就是在centos上启动xrdp,然后通过MS的远程桌面程序进行连接。

在centos端的命令拷贝如下:

sudoyuminstall-ykernel-devel#Neededtore-buildENAdriver

sudoyumgroupinstall-y"ServerwithGUI"

sudosystemctlset-defaultgraphical.target

sudoyum-yinstallepel-release

sudorpm-Uvh/zixunimg/eepwimg/li.nux.ro/download/nux/dextop/el7/x86_64/nux-dextop-release-0-5.e...

sudoyuminstall-yxrdptigervnc-server

sudosystemctlstartxrdp

sudosystemctlenablexrdp

sudosystemctldisablefirewalld

sudosystemctlstopfirewalld

设置完记得给centos用户设置一个密码,否则远程桌面登录不了:

sudopasswdcentos

当你通过远程桌面登录centos后,就可以看到图形化界面了。更多可以参考JeffBar的博客/zixunimg/eepwimg/aws.amazon.com/blogs/aws/developer-preview-ec2-instances-f1-with-programmable-hardware/

以下是从该博客拷贝的远程图形界面截图:

最后希望大家可以在FPGA的世界里找到自己的方向,开始创建自己的芯片系统真是一件让人兴奋的事情。

作者介绍

AWS解决方案架构师;拥有15年IT领域的工作经验,先后在IBM,RIM,Apple等企业担任工程师、架构师等职位;目前就职于AWS,担任解决方案架构师一职。喜欢编程,喜欢各种编程语言,尤其喜欢Lisp。喜欢新技术,喜欢各种技术挑战,目前在集中精力学习分布式计算环境下的机器学习算法。



『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
PLC控制步进电机方法