FPGA meets DevOps - Xilinx Vivado with Docker and Jenkins
In this second blog post of the series “FPGA meets DevOps” I am going show you how to integrate Xilinx Vivado with Docker and Jenkins.
Docker provides a lightweight operating system level virtualisation. It allows developers to package up an application with all the parts it needs in a container, and then ship it out as one package. A container image is described by a file (Dockerfile) which contains a sequence of commands to create the image itself (i.e.: packages to install, configuration tasks, etc) and it is all you need to replicate the exact build environment on another machine.
The objective is to create a container that will run Vivado in headless mode (without user interface) to build the FPGA image.
First install Docker for your Linux distribution, i.e. for Ubuntu: https://docs.docker.com/install/linux/docker-ce/ubuntu/
Then download a full Xilinx Vivado image (not the web installer).
The tar.gz file needs to be provided during the container image creation via a web-server. If you don't have a web-server you can i.e. launch a very simple one written in Python 3, just run this command line from the directory were the Vivado tar.gz file is:
$ python3 -m http.server
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
This will run a web-server listening on port 8000 and providing the content of the directory where the script is run over HTTP.
Clone or download the repository containing the Dockerfile. This is a fork of an existing Vivado docker image (https://github.com/BBN-Q/vivado-docker) with a few customisations.
Git clone https://github.com/starwaredesign/vivado-docker.git
Cloning into 'vivado-docker'...
remote: Enumerating objects: 54, done.
remote: Total 54 (delta 0), reused 0 (delta 0), pack-reused 54
Unpacking objects: 100% (54/54), done.
Checking connectivity... done.
Get a licence for Vivado from the Xilinx website and copy Xilinx.lic inside the vivado-docker directory. Then create the docker image:
$ sudo docker build --build-arg VIVADO_TAR_HOST=192.168.1.100:8000 --build-arg VIVADO_TAR_FILE=Xilinx_Vivado_SDK_2018.3_1207_2324 -t vivado:2018.3 --build-arg VIVADO_VERSION=2018.3 .
Sending build context to Docker daemon 140.3kB
Step 1/17 : FROM ubuntu:16.04
…
Step 17/17 : COPY Xilinx.lic /home/vivado/.Xilinx/
---> 77e6b40ccf04
Successfully built 77e6b40ccf04
Successfully tagged vivado:2018.3
In this example I am creating a Vivado 2018.3 image. You might need to adjust the VIVADO_TAR_HOST and VIVADO_TAR_FILE arguments based on your system configuration.
The creation of the image might take a few minutes.
You can list the available docker images:
$ sudo docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
vivado 2018.3 77e6b40ccf04 10 minutes ago 20.2GB
We can now install Jenkins (https://jenkins.io/). Jenkins is an open source automation tools that helps to automate the build, test and deployment process. Jenkins processes can be triggered by a source version control commit, scheduled i.e. every day or from the completion of another process.
The objective is to get Jenkins to build the FPGA bitstream using the Docker image we've built earlier.
Jenkins itself can run inside a Docker container (https://jenkins.io/doc/book/installing/)
$ sudo docker run \
-u root \
--rm \
-d \
-p 8080:8080 \
-p 50000:50000 \
-v jenkins-data:/var/jenkins_home \
-v /var/run/docker.sock:/var/run/docker.sock \
jenkinsci/blueocean
This will download the Jenkins Docker container and run it. Then get access to Jenkins through a web browser on port 8080. When accessing Jenkins the first time, use the automatically generated admin password that can be found in the docker image logs
$ sudo docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3f99cea6c114 jenkinsci/blueocean "/sbin/tini -- /usr/…" 4 minutes ago Up 4 minutes 0.0.0.0:8080->8080/tcp, 0.0.0.0:50000->50000/tcp musing_haibt
Copy the container ID (in this case 3f99cea6c114)
$ sudo docker logs 3f99cea6c114
And create a first user account. This is a very simple setup that doesn't take into account security of the Jenkins server. Please look at the official documentation (https://jenkins.io/doc/book/system-administration/security/) on how to create users, set permissions, use https, etc.
We're now going to add a Jenkins pipeline script which describes the steps to build the FPGA bitstream. The file is part of the Vivado template or the Vivado example of the previous blog post (https://www.starwaredesign.com/index.php/blog/63-fpga-meets-devops-xilinx-vivado-and-git). This pipeline is very simple, but other steps can be added i.e. running testbenches, building firmware for a softcore CPU, etc.
The pipeline script Jenkinsfile can be found in the folder ci:
pipeline {
agent {
docker {
image 'vivado:2018.3'
}
}
stages {
stage('Checkout') {
steps {
checkout scm
}
}
stage('Build') {
steps {
sh '/bin/bash -l scripts/build_fpga.sh'
}
}
}
post {
always {
archiveArtifacts artifacts: 'vivado/**/impl_1/*.bit'
cleanWs()
}
}
}
The Jenkinsfile describes the agent to be used (the Docker container with Vivado), the steps required (checkout from version control, build using build_fpga.sh) and what to when the build has completed successfully: in this case the bitstream is saved as artifact.
From the Jenkins landing page, select "Add item", add a name for the build configuration and select "Pipeline".
Add the URL of the git repo to be used. I have selected "Do not allow concurrent builds" since I have just one licence.
There are several options to trigger a build: from a commit on the source version control or periodically, etc. The right configuration depends on the type of project. If the build takes hours, probably it is not a good idea to trigger at each version control commit. Maybe once per day (overnight) might be more appropriate.
Then configure where the Jenkins file is stored: inside the git repository inside the ci folder.
The button "build now" can be used to trigger an immediate build.
Now we have a way to recreate a build environment very easily using Docker containers and the build process is fully automated.