亿迅智能制造网
工业4.0先进制造技术信息网站!
首页 | 制造技术 | 制造设备 | 工业物联网 | 工业材料 | 设备保养维修 | 工业编程 |
home  MfgRobots >> 亿迅智能制造网 >  >> Industrial programming >> VHDL

在Linux VPS上用Jenkins、Vivado、GitHub自动化FPGA开发

* 本文含UpCloud VPS广告链接

持续交付与持续集成是敏捷软件开发方法论,缩短代码变更到部署的周期。通过自动化验证代码变更与构建发布文件,团队能更高效、富有成效。

软件公司长期实践持续开发,但FPGA项目同样适用。本教程教您在虚拟专用服务器(VPS)上使用Jenkins、Xilinx Vivado、Git/GitHub源代码管理(SCM)系统搭建自动化服务器。

什么是Jenkins?

Jenkins自动化服务器是用Java编写的免费开源程序。可在Windows或Linux运行。本文使用Linux,因其是无头服务器最常用平台。Jenkins在Linux以守护进程、在Windows以服务运行。启动时内置Web服务器提供用户界面,多数用户通过Web界面交互。可通过Web GUI添加管理自动化项目。

上图展示我们将搭建的Jenkins服务器主页。默认仅登录用户可访问,为本文演示我启用了部分公开访问。*演示服务器已于2020年5月13日下线。

主页显示任务列表。任务可包含任意任务,可从Web GUI手动触发,或通过脚本、webhook、其他任务完成自动触发——故称"自动化服务器"。本例中每个任务对应一个单独GitHub仓库的VHDL模块。Jenkins在开发者推送代码到受监控Git仓库时运行仿真与构建。若测试台失败或构建中断,Jenkins在Web界面标记任务失败,自动邮件通知提交故障代码者。

示例项目

自动化服务器最适合大型项目团队。因此构建包含八个Git仓库的示例FPGA项目——移植到Xilinx ZedBoard的Fast-Track课程7段显示计数器。每个仓库含VHDL模块及其测试台,除packages仓库仅含三个定义常量类型的VHDL包。seg7顶层模块含约束文件定义物理实现的时钟速度与引脚分配。大规模VHDL项目常使用多仓库模块,公司典型复用包与模块库。我通过Git Submodules按需导入解决依赖,上图展示所有仓库内容与依赖。Git仓库也含Jenkins配置、构建脚本等非设计文件,后续章节详述。

虚拟专用服务器(VPS)

Jenkins可运行于任何Windows/Linux电脑,但实际生产需专用服务器。自动化服务器须始终运行并对全团队可访问。若有闲置物理服务器固佳,但多数人用VPS更快更廉。VPS是从主机商租用的虚拟电脑,表现为真实Windows/Linux电脑可交互安装软件。我们用Linux。VHDLwhiz站点已在VPS运行两年,经调研最快最佳提供商是UpCloud,自然用UpCloud搭建自动化服务器VPS。

获$25 UpCloud赠金

若想试用UpCloud,我有推荐码注册送$25信用额度。>> 点此获$25 UpCloud赠金 << 或结账用推荐码NV78V6。使用码获赠金同时支持VHDLwhiz,每位用码客户我可能获UpCloud账户返佣。言归正传,开始搭建服务器。

部署UpCloud VPS

登录UpCloud账户后,服务器→部署服务器创建新VPS实例。选距您最近数据中心。选资源方案:Jenkins占用少但Xilinx Vivado极耗内存,至少选4GB RAM方案。参考Xilinx内存建议页,内存用量与目标FPGA复杂度相关。Zynq-7000 XC7Z045峰值内存1.9GB,我2GB方案路由时不足,Vivado崩溃,dmesg日志现"Out of memory: Killed process (vivado)"。可随时升级RAM/CPU,但额外硬盘空间需重新分区。参考:我从50GB存储起步,完成自动化服务器后用61%,Vivado单独占24GB。建议选最新CentOS Linux发行版,Vivado官方仅支持Red Hat Linux(收费),CentOS是紧跟Red Hat的免费社区支持发行版。网络选项保持默认,可上传SSH密钥免密登录。指定主机名与服务器名,主机名为用户浏览器访问Jenkins的公共域名,无域名可用IP。设置满意点部署创建服务器。创建后自动生成密码显示通知,可用Linux passwd 命令修改。若部署前提供SSH密钥则无需密码。若失去访问,可在UpCloud账户点打开控制台连接登录。

DNS区域设置

新服务器获永久IPv4/IPv6地址,在服务器→网络查看。SSH登录root@公网IPv4。仅用IP做实验可行,但分配永久域名更实用。需从注册商购买域名。我用vhdlwhiz.com域名创建子域名jenkins.vhdlwhiz.com。部署时在UpCloud正确设置服务器域名。下一步在域名注册商DNS区域文件指向公网IPv4。修改DNS生效通常≤20分钟,极端情况48小时。生效后可用域名替代IP通过SSH登录:

ssh root@yoursub.yourdomain.com

安装Jenkins

SSH登录root后首要更新所有已装包。CentOS用yum包管理器。执行yum -y update更新至最新版。安装Jenkins前显式安装Java 11,避免后续装Vivado麻烦。当前服务器无Java,直接yum装Jenkins会装Java 8,虽适配Jenkins但Vivado依赖Java 11。执行yum -y install java-11-openjdk-devel安装Java 11。Jenkins不在CentOS默认仓库,从Red Hat导入Jenkins仓库:

wget -O /etc/yum.repos.d/jenkins.repo https://pkg.jenkins.io/redhat/jenkins.repo
rpm --import https://pkg.jenkins.io/redhat/jenkins.io.key
然后安装Jenkins:yum -y install jenkins。下次启动自动启动Jenkins,无需重启可用systemctl start jenkins。用systemctl status jenkins查看状态与错误信息。

Jenkins不安全HTTP访问

此时Jenkins在VPS 8080端口运行,但浏览器无法连接。CentOS防火墙默认阻断8080和80(HTTP)端口。可开放80端口并用iptables重定向到8080。但先决定是否用HTTPS保护。仅用HTTP和80端口网站不安全,公共Wi-Fi下恶意者可窃听窃取Jenkins登录凭证。若要避免未加密HTTP安全风险,跳至下节配置HTTPS。否则继续。 启用不安全HTTP访问:

firewall-cmd --permanent --zone=public --add-port=80/tcp
firewall-cmd --reload
iptables -A PREROUTING -t nat -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 8080
浏览器输入域名应现Jenkins入门页,Chrome地址栏显示"不安全"警告。满意可跳至设置Jenkins节。

Jenkins安全HTTPS访问

公开访问的不安全网站风险巨大。Jenkins访问源代码,黑客入侵服务器也能访问。幸好几条命令即可加固。Jenkins自身不处理HTTPS,需装通用Web服务器将安全通道请求转发给不安全Jenkins。用Nginx,最流行免费开源Web服务器之一。

yum -y install nginx
systemctl start nginx
防火墙开放HTTP和HTTPS端口。虽仅服务HTTPS,但需保HTTP开放让Nginx重定向不安全请求至安全端口。
firewall-cmd --permanent --zone=public --add-port=80/tcp
firewall-cmd --permanent --zone=public --add-port=443/tcp
firewall-cmd --reload
用免费Let's Encrypt CA获取浏览器验证证书。certbot脚本自动完成。
apt update
apt install snapd
snap install core; snap refresh core
snap install --classic certbot
运行脚本安装证书并修改Nginx配置。脚本提问均答Yes/Accept,直到问是否重定向HTTP到HTTPS,选2: Redirect。
... Deploying Certificate to VirtualHost /etc/nginx/nginx.conf
Please choose whether or not to redirect HTTP traffic to HTTPS...
1: No redirect...
2: Redirect - Make all requests redirect to secure HTTPS access...
Select [1-2] then [enter] (press 'c' to cancel): 2
添加每日cron job自动续期证书:
echo "0 0 * * * /snap/bin/certbot renew --quiet" | crontab -
cron守护进程每日午夜运行续期脚本。crontab -l列出、crontab -e编辑cron job。访问网站现显Nginx测试页而非Jenkins,稍后修复,确认Chrome地址栏"不安全"警告消失。修改/etc/nginx/nginx.conf让Nginx服务Jenkins。用nano编辑:
nano /etc/nginx/nginx.conf
找列出您域名的server块,添加高亮行(第一行加server块上方,其余加root location块内)。更新配置后重载Nginx生效。可选nginx -t测试配置。systemctl reload nginx重载。现浏览器访问Jenkins站点应见入门页,且通过安全连接,可安全在Web GUI配置Jenkins。

设置Jenkins

首次访问Jenkins网站提示输入Linux文件系统文件中的密码。SSH登录时用cat /var/lib/jenkins/secrets/initialAdminPassword显示密码,复制粘贴到浏览器访问Web GUI。下屏选安装建议插件或指定插件,选安装建议插件。下页创建管理员用户,填详情设强密码。默认仅登录用户可访问,匿名用户仅见登录框。我演示站点jenkins.vhdlwhiz.com可匿名访问因我修改了服务器,用Matrix Authorization Strategy插件授予匿名访问部分视图。*演示站点2020年5月13日下线。插件装完显"Jenkins已就绪!",点按钮进入全新Jenkins空概览页。

安装Jenkins插件

侧边栏选管理Jenkins→管理插件→可用。搜索框输入内容才显示插件。安装我示例Jenkins服务器用的插件:

Blue Ocean

首推Blue Ocean。这插件现代化Jenkins工作流与UI,还拉取一堆有用插件免单独装。插件管理器搜"blue ocean"选装。安装进度页可选安装完成且无任务运行时重启Jenkins。或SSH执行systemctl restart jenkins重启。除Blue Ocean拉取的长列表插件,初看无明显变化。但侧边栏新增菜单项,点击进入Blue Ocean GUI,界面大异常规Jenkins。试试!

Green Balls

纯美观插件。搜"green ball"装上。Jenkins默认用蓝球指示任务成功。因Jenkins发明者是日本人,日本蓝色可互换绿色表示OK。详见此文作者亲述。世界其他地区用户多偏好绿球,Green Balls插件轻松修正。

Locale插件

搜"locale"装上。插件强制Jenkins对所有用户用同语言GUI。默认Jenkins按浏览器语言翻译UI。我是挪威人但想用英文,翻译不全。且英文谷歌答案更易找。安装后去管理Jenkins→配置系统找Locale节,填"en_US"(或想要语言)并勾选强制所有用户,拉到底点保存。

Sidebar Link插件

搜"sidebar"装上。允许侧边栏加自定义链接,稍后用来链接FPGA发布(bitfiles)。

连接Jenkins到GitHub

无论仓库公开私有,需给Jenkins GitHub权限。最简方式让Jenkins GitHub插件管理GitHub接口。Blue Ocean已装GitHub插件。配置步骤:

GitHub个人访问令牌

登录GitHub,点右上角头像→Settings→Developer Settings→左栏Personal access tokens。点Generate new token。GitHub再次要密码。本质创建应用专用密码,可撤销、可限权限。命名如"Jenkins"。至少启用admin:org_hook、admin:repo_hook、repo权限。点Generate token,令牌出现,**离页前必须复制**,无法再次查看。忘记则删重建。

在Jenkins录入GitHub凭据

复制令牌后去Jenkins,管理Jenkins→配置系统找GitHub节。下拉选Add GitHub Server→GitHub Server。新现GitHub Server节勾选Manage hooks,Jenkins将为监控仓库在GitHub装webhook,稍后用触发用户推代码时Jenkins仿真/构建。选Credentials (Add)→Jenkins。弹窗中Kind改Secret text,Secret粘贴GitHub生成的个人访问令牌,ID写"GitHub"点Add。回主配置菜单,Credentials菜单选新GitHub键,点Test connection验证Jenkins能用令牌与GitHub通讯。成功应见确认信息。离开配置页前务必拉到底点保存。 若麻烦添多凭据,去管理Jenkins→管理用户点用户名,左栏Credentials查看编辑Jenkins存储的所有密钥。

配置Jenkins发邮件

配置Jenkins代码出错时自动发邮件。在管理Jenkins→配置系统修改:System Admin e-mail address填Jenkins发件地址。最好用Jenkins域名结尾地址,降低进垃圾箱几率。Jenkins服务器无权代表其他域名发信,但多数邮件服务接受发件服务器同域的发件地址。下图我用Jenkins域名同域发件地址。给Jenkins发信方式:最直接在VPS装SMTP服务器。SSH执行:

yum -y install sendmail
systemctl enable sendmail
systemctl restart sendmail
装好sendmail回Jenkins系统配置,SMTP server填"localhost"。可勾选允许发送给未注册用户(无Jenkins账户)。稍后配置Jenkins发邮件给推故障代码者,Jenkins从GitHub取邮箱,但仅当该人有匹配Jenkins账户或勾此框才生效。可测试配置,显"Email was successfully sent"且收件箱收到邮件。5分钟内未收检查垃圾箱。

批量模式安装Xilinx Vivado

示例项目用Xilinx Vivado仿真、编译、实现代码,目标器件ZedBoard开发板上Xilinx Zynq-7000 FPGA。本节展示用免费WebPACK许可在VPS装Vivado。下载Xilinx Unified Installer: Linux Self Extracting Web Installer,需登录或创建Xilinx账户。下载完从桌面电脑复制到Jenkins服务器。桌面有Linux shell建议用安全文件复制。运行安装器前装依赖包:

yum -y install tar
yum -y install java-11-openjdk-devel
yum -y install ncurses-compat-libs
yum -y install gcc
运行Xilinx Unified安装器:
./Xilinx_Unified_2019.2_1106_2127_Lin64.bin --keep --noexec --target Xil_installer
.bin文件解包安装文件到新目录Xil_installer。报错"Uncompressing Xilinx Installer Extraction failed. Terminated"因未装tar。Xilinx Unified安装器可装多种Xilinx工具,需在Xil_installer目录运行xsetup指定软件:
cd Xil_installer/
./xsetup -b ConfigGen
xsetup提示选工具:输"2"选Vivado,输"1"选Vivado HL WebPACK。
Select a Product from the list:
1. Vitis 2. Vivado 3. On-Premises Install for Cloud Deployments...
Please choose: 2
Select an Edition from the list:
1. Vivado HL WebPACK 2. Vivado HL Design Edition 3. Vivado HL System Edition
Please choose: 1
装WebPACK版须安装时登录Xilinx账户。桌面GUI引导,服务器无GUI,用xsetup脚本认证。运行命令生成认证令牌,输几次才成功,先报"Internet connection validated, can connect to internet"错,几次后通过,输入下载安装器用的邮箱密码。准备好批量模式装Vivado。调用setup脚本须指定安装配置文件让xsetup知下载哪工具。配置文件在root用户家目录.Xilinx文件夹。运行:
./xsetup -a XilinxEULA,3rdPartyEULA,WebTalkTerms \
-b Install -c ~/.Xilinx/install_config.txt
安装耗时长。Vivado装24GB空间,从较慢Xilinx服务器下载,我下载超两小时。装完测试Vivado批量模式成功启动。Xilinx提供shell脚本设环境。运行Vivado前用source加载脚本:
source /tools/Xilinx/Vivado/2019.2/settings64.sh
服务器无GUI环境,批量模式启动:vivado -mode batch。Vivado启动即退出无报错,表明一切就绪。报错"application-specific initialization failed: couldn't load file "librdi_commontasks.so": libtinfo.so.5: cannot open shared object file: No such file or directory"因未装ncurses-compat-libs。

在Jenkins集成Vivado

准备Jenkins用Vivado,去管理Jenkins→配置系统检查默认设置。Vivado极耗内存,用量视目标FPGA而定,可参考Xilinx Memory Recommendations页。建议将默认并行任务数从2改1。除非VPS分配巨大RAM,可能想设# of executors为1。不用每个Jenkins任务定环境变量,全局指定所有任务的PATH,方便未来换新版Vivado。脚本引用'vivado'可执行文件始终指向最新版或您决定版本。滚动到Global properties勾选Environment variables点Add新条目。含标准LinuxPATH,我用"PATH=/tools/Xilinx/Vivado/2019.2/bin:/sbin:/usr/sbin:/bin:/usr/bin"。别忘拉到底点保存。

批量模式下的Vivado GUI项目

我选GUI模式管理Vivado项目。每个仓库在常规Vivado GUI新建项目,加源文件、设库等。但.xpr项目文件是二进制且依赖项目目录大量临时文件。二进制文件不适合Git等SCM。幸好Xilinx想到这点,写了指南(XAPP1165)讲Vivado配合版本控制。用Vivadowrite_project_tcl命令导出整个项目为Tcl脚本,含适合Git的可读Tcl代码。我整理所有Git仓库,Vivado项目文件在"vivado"子文件夹,VHDL源文件在父目录。看我GitHub演示packages项目。每个仓库将Vivado Tcl脚本放vivado文件夹,含create_vivado_proj.tcl——Vivado项目的人类可读版。创建create_vivado_proj.tcl:在Vivado GUI按意愿建好项目,确保项目在vivado子文件夹。满意后在Vivado Tcl控制台输:

cd [get_property DIRECTORY [current_project]]
write_project_tcl -force -target_proj_dir . create_vivado_proj
将create_vivado_proj.tcl加入Git,设gitignore忽略vivado文件夹其余文件。我的.gitignore忽略vivado文件夹除Tcl脚本外所有:

批量模式打开Vivado项目

创建Jenkins任务前在VPS手动测试Vivado项目好。守护进程默认在Linux服务器jenkins用户账户运行。故用jenkins用户测试。确保Linux服务器装Git。root登录后执行装Git。不能直接登录jenkins用户,但可从root切换:su - jenkins。运行pwd见在/var/lib/jenkins。这非常规用户家目录在/home,仅运行Jenkins守护进程,但可登录在Jenkins环境手动演练构建过程。家目录全是日志、用户设置、下载插件等动态数据。稍后在Jenkins GUI跑任务会出现在jobs文件夹。去jobs文件夹实验:

cd /var/lib/jenkins/jobs/
直接克隆Git仓库到jobs文件夹。Git仓库须免密访问,因公开或按GitHub帮助页设免密登录。若无现成含Vivado项目的Git仓库,可克隆我仓库:
git clone https://github.com/jonasjj/Jenkins-demo-packages
cd进新Git仓库目录,再进vivado文件夹:
cd Jenkins-demo-packages/vivado/
下载我示例会见两Tcl文件:create_vivado_proj.tcl和check_syntax.tcl。前者是转Tcl的Vivado项目,后者是检查Vivado项目VHDL文件语法的脚本。跑Vivado命令前需在当前shell设PATH环境变量。Jenkins用Global properties解决,现在不通过Jenkins,须source Xilinx设置脚本:
source /tools/Xilinx/Vivado/2019.2/settings64.sh
现在vivado可执行文件在path,先重建项目。批量模式Vivado重建项目命令:
vivado -mode batch -source create_vivado_proj.tcl
回车后见大量Tcl代码回显控制台,是重建Vivado项目的代码在执行。若无明显错,输echo $?前不做别的事。输出应为0表示全好:
INFO: [Common 17-206] Exiting Vivado at Sun Apr 19 18:32:48 2020...
[jenkins@jenkins vivado]$ echo $?
0
echo $?显示Linux上一条命令退出状态。0=OK无错,非0=错。Unix老惯例。退出状态对Jenkins重要,因据此决定任务阶段成功或失败。目录列表见Vivado重建项目二进制文件。再试跑Tcl脚本。创建单行Tcl脚本:echo "exit 1" > test.tcl。批量模式跑:
vivado -mode batch -source test.tcl
Vivado关闭后再查退出码:
[jenkins@jenkins vivado]# echo $?
1
为1=Unix退出失败。改test.tcl内容为"exit 0"再跑Vivado,退出状态变0=成功。试试!实验满意后删jobs文件夹测试项目:
cd /var/lib/jenkins/jobs/
[jenkins@jenkins jobs]# rm -rf Jenkins-demo-packages

Vivado中检查代码语法的Tcl脚本

此Tcl脚本跑项目VHDL文件语法检查。若要仿真或实现代码不需此脚本,因语法错会断编译。但packages项目无测试台意义,文件仅含常量类型声明。仍想捕获推送到此仓库的编码错,语法检查派上用场。脚本如下:开项目文件,调用Vivadocheck_syntax命令输出存变量msg。检查完看输出消息有无报错。check_syntax报任何东西则退出状态1(失败),无错退出0(成功)。

# Check for syntax errors
# Return exit code 1 on error, else 0
open_proj packages.xpr
set msg [check_syntax -fileset sim_1 -return_string]
set ret_val 0
if {$msg != ""} {
set ret_val 1
}
puts $msg
exit $ret_val
Vivado支持所有标准Tcl关键字,还有大量内置命令如check_syntax。建议看两份Xilinx文档详述Tcl脚本能力:Vivado Design Suite Tcl Command Reference Guide (UG835)、Vivado Design Suite User Guide Using Tcl Scripting (UG894)。

Vivado中仿真的Tcl脚本

下个脚本跑测试台批量模式。须在导出Tcl前在Vivado GUI配置仿真集。用create_vivado_proj.tcl脚本重建桌面电脑仿真项目看我咋预设。可在Vivado GUI打开重建项目。脚本:开项目,设仿真文件集名变量(通常sim_1)。启动仿真后也须关闭,否则仿真状态不写入日志。

open_proj seg7.xpr
set sim_fileset sim_1
launch_simulation -simset [get_filesets $sim_fileset]
close_sim
# Look for assertion failures in the simulation log
set log_file [glob *sim/$sim_fileset/behav/xsim/simulate.log]
set fp [open $log_file]
set file_data [read $fp]
exit [regex "Failure:" $file_data]
我曾挣扎找好方法获仿真状态。我的VHDL测试台成功时用VHDLfinish关键字终止。错导致VHDL断言失败。用Vivado Tcl命令无显式方式知模拟器为何停。幸好Tcl强大脚本语言。变通法:开仿真日志找"Failure:"字符串——指示VHDL断言失败。日志含该词退出1,不含退出0。

Vivado中综合的Tcl脚本

批量模式Vivado综合Tcl脚本:开项目文件,赋运行名变量。导出Tcl前须在GUI加设计文件到Vivado项目。若未改GUI综合运行名,大概率是"synth_1"。设CPU计数变量为服务器逻辑处理器数,控制Vivado多线程度。我选UpCloud 4 CPU VPS,设CPU计数4。

open_proj seg7.xpr
set run_name synth_1
set cpu_count 4
reset_runs $run_name
launch_runs $run_name -jobs $cpu_count
wait_on_run $run_name
set status [get_property STATUS [get_runs $run_name]]
if {$status != "synth_design Complete!"} {
exit 1
}
exit 0
launch_runs非阻塞,即实际综合前完成。若launch_run后即读状态,会是"Running"。为暂停脚本等综合完成,调wait_on_run。最后取运行状态,视状态消息退出0或1。

Vivado中实现(Place and Route)的Tcl脚本

批量模式Vivado PAR脚本类似综合脚本。区别:运行名变"impl_1",找另一成功消息。

open_proj seg7.xpr
set run_name impl_1
set cpu_count 4
reset_runs $run_name
launch_runs $run_name -jobs $cpu_count
wait_on_run $run_name
set status [get_property STATUS [get_runs $run_name]]
if {$status != "route_design Complete!"} {
exit 1
}
exit 0

Vivado中生成比特流的Tcl脚本

实现成功后生成比特流编程FPGA。脚本类似前者,但launch_runs命令略不同,找不同状态。

open_proj seg7.xpr
set run_name impl_1
set cpu_count 4
launch_runs $run_name -to_step write_bitstream -jobs $cpu_count
wait_on_run $run_name
set status [get_property STATUS [get_runs $run_name]]
if {$status != "write_bitstream Complete!"} {
exit 1
}
exit 0

设置Jenkins任务

Jenkins任务指一组分组软件任务。Jenkins概览页列表显示任务及当前状态。可从Web界面手动启动,或自动触发如推代码到仓库、其他任务完成。两者皆用。Jenkins管理任务有多种方式。传统Freestyle project在Jenkins Web GUI指定每动作。更现代方式用流水线脚本存储执行流所有信息,流水线脚本益于可加入SCM。创建新流水线脚本:侧边栏选New item,弹窗选Pipeline点OK。任务配置首要加含源码GitHub仓库。本例用packages仓库,其他任务仓库同过程。勾GitHub project,现现Project url填地址。设构建触发器:想代码推送到GitHub仓库时启动任务。勾GitHub hook trigger for GITScm polling。注:仅全局设置勾Manage hooks时生效。任务配置页底Pipeline节。可直接在配置页输流水线脚本。但想版本控制流水线脚本,选Pipeline script from SCM。确保选Git。粘贴GitHub仓库URL,私有仓库选凭据。我们公开留空凭据。用默认master分支。选Git仓库内Jenkins脚本路径。我每仓库根目录创建Jenkinsfile。离开页前点保存。

Jenkins流水线脚本

流水线脚本遵循Apache Groovy语法规则,我承认之前从未听说。但若做过任何现代编程不难理解。乍看像无逗号分隔数据项的JSON模式。脚本通用,有并行执行阶段、多Jenkins服务器跑任务等选项。建议看官方Jenkins流水线文档深入。幸好不必全懂即受益。用下格式作所有脚本模板,按需加阶段分逻辑步骤。

pipeline {
agent any
stages {
stage('Stage name 1') {
steps {
// Command 1
// Command 2
// Etc.
}
}
stage('Stage name 2') {
steps {
// Command 1
// Command 2
// Etc.
}
}
}
post {
failure {
emailext attachLog: true, body: '''Project name: $PROJECT_NAME
Build number: $BUILD_NUMBER
Build Status: $BUILD_STATUS
Build URL: $BUILD_URL''',
recipientProviders: [culprits()],
subject: 'Project \'$PROJECT_NAME\' is broken'
}
}
}
有人推故障代码到仓库,想肇事者收自动邮件含失败任务信息。用post节内failure节。仅任一阶段失败执行此部。任务停止,Jenkins不去下阶段,跳入failure节。Jenkins从最新Git提交提取邮箱发邮件含损坏构建链接。

VHDL语法检查任务

我们设计中仅packages仓库无测试台,用check_syntax.tcl验证代码至少是有效VHDL。流水线脚本第一步调deleteDir()——Jenkins流水线脚本基本命令,清理工作区移除前构建残留。下行调git——非Linuxgit命令,引用git Jenkins插件。克隆仓库到工作区。Create project阶段第三行用sh关键字调Linux shell命令。进vivado目录跑create_vivado_proj.tcl脚本在Vivado批量模式重建Vivado项目。

pipeline {
agent any
stages {
stage('Create project') {
steps {
deleteDir() // clean up workspace
git 'https://github.com/jonasjj/Jenkins-demo-packages'
sh 'cd vivado && vivado -mode batch -source create_vivado_proj.tcl'
}
}
stage('Check VHDL syntax') {
steps {
sh 'cd vivado && vivado -mode batch -source check_syntax.tcl'
}
}
}
post {
failure {
emailext attachLog: true, body: '''Project name: $PROJECT_NAME
Build number: $BUILD_NUMBER
Build Status: $BUILD_STATUS
Build URL: $BUILD_URL''',
recipientProviders: [culprits()],
subject: 'Project \'$PROJECT_NAME\' is broken'
}
}
}
第二阶段Check VHDL syntax,Vivado项目已存在,跳到跑Tcl脚本。再用shell命令跑check_syntax.tcl,成功退出0、错退出1致Jenkins标记构建失败。

VHDL仿真任务

除packages仓库外所有任务,git单行命令不管用检出GitHub代码。因这些仓库有子模块依赖。子模块引用其他Git仓库,简单git命令不默认拉取。但可用更通用checkout调用修复,Git插件页有详细文档。

pipeline {
agent any
stages {
stage('Create project') {
steps {
deleteDir() // clean up workspace
checkout([$class: 'GitSCM', branches: [[name: '*/master']],
doGenerateSubmoduleConfigurations: false,
extensions: [[$class: 'SubmoduleOption',
disableSubmodules: false,
parentCredentials: false,
recursiveSubmodules: true,
reference: '',
trackingSubmodules: true]],
submoduleCfg: [],
userRemoteConfigs: [[
url: 'https://github.com/jonasjj/Jenkins-demo-bcd_encoder']]])
sh 'cd vivado && vivado -mode batch -source create_vivado_proj.tcl'
}
}
stage('Run simulation') {
steps {
sh 'cd vivado && vivado -mode batch -source run_simulation.tcl'
}
}
}
post {
failure {
emailext attachLog: true, body: '''Project name: $PROJECT_NAME
Build number: $BUILD_NUMBER
Build Status: $BUILD_STATUS
Build URL: $BUILD_URL''',
recipientProviders: [culprits()],
subject: 'Project \'$PROJECT_NAME\' is broken'
}
}
}
下阶段跑run_simulation.tcl脚本在Vivado。上列脚本用于bcd_encoder仓库。counter、digit_selector、output_mux、reset、seg7_encoder仓库用相同脚本,仅仓库URL不同。

FPGA实现任务

seg7仓库含FPGA项目顶层模块,作为子模块拉取所有其他仓库。流水线脚本类似仿真任务,但增四阶段:Run simulation、Run implementation、Generate bitstream、Release bitfile。前两阶段建项目跑仿真,前文已覆盖。后三阶段同理,换相关Tcl脚本。

pipeline {
agent any
stages {
stage('Create project') {
steps {
deleteDir() // clean up workspace
checkout([$class: 'GitSCM', branches: [[name: '*/master']],
doGenerateSubmoduleConfigurations: false,
extensions: [[$class: 'SubmoduleOption',
disableSubmodules: false,
parentCredentials: false,
recursiveSubmodules: true,
reference: '',
trackingSubmodules: true]],
submoduleCfg: [],
userRemoteConfigs: [[
url: 'https://github.com/jonasjj/Jenkins-demo-seg7']]])
sh 'cd vivado && vivado -mode batch -source create_vivado_proj.tcl'
}
}
stage('Run simulation') {
steps {
sh 'cd vivado && vivado -mode batch -source run_simulation.tcl'
}
}
stage('Run synthesis') {
steps {
sh 'cd vivado && vivado -mode batch -source run_synthesis.tcl'
}
}
stage('Run implementation') {
steps {
sh 'cd vivado && vivado -mode batch -source run_implementation.tcl'
}
}
stage('Generate bitstream') {
steps {
sh 'cd vivado && vivado -mode batch -source generate_bitstream.tcl'
}
}
stage('Release bitfile') {
steps {
sh '''
PROJ_NAME=seg7
RELEASE_DIR=/usr/share/nginx/html/releases/
BASE_NAME=$PROJ_NAME-`date +"%Y-%m-%d-%H-%H:%M"`
BITFILE=$BASE_NAME.bit
INFOFILE=$BASE_NAME.txt
git log -n 1 --pretty=format:"%H" >> $INFOFILE
echo -n " $PROJ_NAME " >> $INFOFILE
git describe --all >> $INFOFILE
echo "" >> $INFOFILE
echo "Submodules:" >> $INFOFILE
git submodule status >> $INFOFILE
cp $INFOFILE $RELEASE_DIR
cp vivado/seg7.runs/impl_1/top.bit $RELEASE_DIR/$BITFILE
'''
}
}
}
post {
failure {
emailext attachLog: true, body: '''Project name: $PROJECT_NAME
Build number: $BUILD_NUMBER
Build Status: $BUILD_STATUS
Build URL: $BUILD_URL''',
recipientProviders: [culprits()],
subject: 'Project \'$PROJECT_NAME\' is broken'
}
}
}
实现任务最终阶段Release bitfile含shell脚本复制新生成FPGA编程文件到发布文件夹。shell命令重命名文件含项目名与时间戳。为保可追溯,生成文本文件含主仓库(seg7)Git哈希及所有子模块。用Git子模块时仅存主仓库哈希不够。为生成含所有子模块变更的主仓库哈希,须拉取更新所有子模块后提交主仓库。不想从Jenkins自动提交。注:对真实Jenkins项目,每次推送都实现FPGA如示例做法可能不妥。大规模FPGA项目路由可耗数小时,团队开发者每天多次推送时不适用。可配置Jenkins每天只路由一次,如午夜,见任务配置页截图。

其他任务完成后触发构建

示例项目含多Git仓库,但作为Git子模块关联。除packages,所有其他仓库依赖至少另一仓库。大多依赖packages仓库。看文前依赖图咋组合。故应不仅在推代码到相关仓库时触发任务,也在任一子模块被触动后触发。Jenkins中访问每任务设Build after other projects are built选项实现。下图显示bcd_encoder项目触发器:依赖的packages仓库成功完成构建后启动。顶层模块依赖所有其他仓库,我用逗号分隔列表加为监视项目。注:若FPGA实现任务路由耗时长,如前节所述,可能不想对实现任务这么做。

用Nginx服务比特流文件

已有Web服务器运行,可用其HTTP服务发布文件。想所有新比特流现jenkins.vhdlwhiz.com/releases。看咋用Nginx。实现任务已复制新比特流到Nginx HTML根目录下目录,但未创建。创建发布目录赋jenkins用户写权限:

mkdir /usr/share/nginx/html/releases/
chown jenkins.root /usr/share/nginx/html/releases/
改/etc/nginx/nginx.conf。找名等于您域名的server节,在其内根('/') location节下方直接加location节:
location ^~ /releases {
alias /usr/share/nginx/html/releases/;
autoindex on;
}
保存后测试配置文件、重载Nginx:
nginx -t
systemctl reload nginx
一切顺利应能列出发布目录内容,如Chrome截图。将Jenkins Web界面链接到发布目录,想从Jenkins侧边栏创建链接。已装Sidebar Link插件支持侧边栏自定义链接。去管理Jenkins→配置系统滚到Additional Sidebar Links节。指定新链接名与URL,如图。链接图标字段可选,我复用Jenkins自带图标。完成后侧边栏现有漂亮文件夹图标的比特流发布自定义链接,如图。

总结

Jenkins对FPGA团队也是宝贵工具。自动化任务节省公司时间、提升代码质量。用自动构建触发器与自动化任务流水线,更少编码错误被忽视。如本文示例项目所示,Jenkins可为您VHDL代码实现完整回归测试套件。以愉悦图形Web界面显示项目当前健康状况,甚至最不懂VHDL的项目经理也适用。若想尝试Jenkins做FPGA开发,建议在UpCloud VPS实例按本文步骤操作。几年前移VHDLwhiz到VPS前我深度调研所有VPS提供商,发现UpCloud最快最佳。我对服务100%满意。若决定开UpCloud账户,恳请用我的推荐链接或码:NV78V6。不仅支持VHDLwhiz,用推荐码您也获$25 UpCloud信用额度。

VHDL

  1. VHDL基础测验第4部分:验证你的理解
  2. VHDL进阶测验第2部分:测试你的HDL专业知识
  3. 掌握VHDL有符号与无符号类型:实战洞察
  4. 设计基于 FPGA 的 RC 舵机控制器:精准 PWM 实现
  5. 在VHDL中使用过程:用可复用代码简化设计
  6. 理解 VHDL 中信号与变量的区别
  7. ModelSim 仿真中查看 VHDL 变量的完整技巧
  8. 在 VHDL 进程中使用敏感度列表实现可靠的 RTL 设计
  9. FPGA入门实战:LED闪烁教程(VHDL与Verilog)
  10. 掌握VHDL Case-When语句:高效多路选择器设计
  11. 基于Tcl的交互式测试平台增强硬件验证
  12. 掌握 VHDL Loop 与 Exit 构造:实用指南