Manufactura industrial
Internet industrial de las cosas | Materiales industriales | Mantenimiento y reparación de equipos | Programación industrial |
home  MfgRobots >> Manufactura industrial >  >> Industrial programming >> VHDL

Automatice el desarrollo de FPGA con Jenkins, Vivado y GitHub en un VPS Linux

* Este artículo contiene un enlace publicitario para UpCloud VPS

La entrega continua y la integración continua son metodologías ágiles de desarrollo de software que acortan el tiempo del ciclo entre el cambio de código y la implementación. Al utilizar la automatización para verificar los cambios de código y crear archivos de lanzamiento, los equipos pueden volverse más productivos y eficientes.

Las empresas de software llevan mucho tiempo practicando el desarrollo continuo, pero usted también puede utilizar estos métodos para sus proyectos FPGA. Este tutorial le enseña cómo configurar un servidor de automatización en un servidor privado virtual (VPS) usando Jenkins, Xilinx Vivado y el sistema de gestión de control de fuente (SCM) Git/GitHub.

¿Qué es Jenkins?

El servidor de automatización Jenkins es un programa gratuito y de código abierto escrito en Java. Se ejecuta en Windows o Linux. Usaremos Linux en esta publicación de blog porque es la plataforma más común para servidores sin cabeza.

Jenkins se ejecuta como un proceso demonio en Linux o como un servicio en Windows. Un servidor web integrado que Jenkins inicia cuando se inicia proporciona la interfaz de usuario. La mayoría de los usuarios interactuarán con Jenkins mediante la interfaz web. Puede agregar nuevos proyectos de automatización y administrar los existentes a través de la GUI web.

La imagen de arriba muestra la página principal del servidor Jenkins que configuraremos hoy. De forma predeterminada, solo los usuarios que han iniciado sesión pueden acceder a Jenkins, pero para este artículo, he habilitado el acceso público a partes de mi *servidor de demostración.

* Actualización:eliminé el servidor de demostración el 13 de mayo de 2020

Lo que ves en la página principal es una lista de trabajos. Estos trabajos pueden contener cualquier tarea y se pueden activar manualmente desde la GUI web. O pueden activarse automáticamente a través de scripts, webhooks o como resultado de la finalización de otros trabajos. De ahí el término servidor de automatización .

En nuestro ejemplo, cada trabajo corresponde a un módulo VHDL guardado en un repositorio de GitHub separado. Haremos que Jenkins ejecute una simulación y construya el proyecto cada vez que un desarrollador envíe código a uno de los repositorios de Git monitoreados. Si un banco de pruebas falla o si la compilación falla, Jenkins marcará el trabajo como fallido en la interfaz web y enviará automáticamente un correo electrónico a la persona que cometió el código defectuoso.

El proyecto de ejemplo

Los servidores de automatización son más útiles para equipos que trabajan en proyectos más grandes. Por lo tanto, construí un proyecto FPGA de ejemplo que consta de ocho repositorios Git. El proyecto es el contador de pantalla de 7 segmentos del curso Fast-Track trasladado al Xilinx ZedBoard.

Enlaces a los ocho repositorios en GitHub:

Cada repositorio contiene un módulo VHDL y su banco de pruebas. Una excepción son los paquetes repo, que contiene solo tres paquetes VHDL que definen constantes y tipos. Además, el seg7 El módulo superior contiene un archivo de restricciones que define la velocidad del reloj y las asignaciones de pines de la implementación física.

La mayoría de los proyectos VHDL a gran escala utilizan módulos de más de un repositorio. Las empresas suelen tener una biblioteca de paquetes y módulos que reutilizan en muchos diseños. Eso es lo que estoy emulando al dividir este diseño bastante simple en tantos módulos.

En nuestro ejemplo, todos los módulos dependen del repositorio de paquetes y el módulo superior también depende de todos los submódulos. Resolví esto importándolos según sea necesario mediante el uso de submódulos estándar de Git. El gráfico anterior muestra el contenido y las dependencias de todos los repositorios de este proyecto.

Los repositorios de Git también contienen varios archivos que no son de diseño, como la configuración de Jenkins y los scripts de compilación. Hablaremos de ellos en las próximas secciones de este artículo.

Servidor privado virtual (VPS)

Si bien Jenkins puede ejecutarse en cualquier computadora con Windows o Linux, a efectos prácticos, querrás ejecutarlo en un servidor dedicado. El servidor de automatización debe estar siempre en funcionamiento y accesible para todos los miembros de su equipo. Si tienes un servidor físico con capacidad suficiente, genial. Pero para la mayoría de nosotros, una solución más rápida y económica es utilizar un servidor privado virtual (VPS).

Un VPS es una computadora virtual que se alquila a una empresa de hosting a través de Internet. Aparece como una computadora real con Windows o Linux con la que puedes interactuar e instalar cualquier software que desees. Usaremos una computadora con Linux porque eso es lo que tiene más sentido para nuestro caso de uso.

El sitio VHDLwhiz se ejecuta en un VPS, como lo ha sido durante los últimos dos años. Ya me he tomado la molestia de encontrar el mejor y más rápido proveedor de VPS, que es UpCloud. Naturalmente, usaremos UpCloud para configurar el VPS para nuestro servidor de automatización.

Obtén el bono UpCloud de $25

Si deseas probar UpCloud, tengo un código de referencia que te dará $25 de crédito al registrarse.

>> Haga clic aquí para obtener el bono UpCloud de $25 <<

O use mi código de promoción durante el pago:NV78V6

Al usar el código, obtendrás el bono y admitirás VHDLwhiz al mismo tiempo. Es posible que se me acrediten algunos fondos en mi cuenta de UpCloud por cada cliente que la utilice.

Bien, basta de charlas de ventas. Sigamos con la configuración del servidor.

Implementación del VPS UpCloud

Después de haber iniciado sesión en su nueva cuenta de UpCloud, puede iniciar el proceso de creación de una nueva instancia de VPS navegando a Servidores → Implementar servidor .

UpCloud tiene muchos centros de datos en todo el mundo. Seleccione la ubicación más cercana a usted para alojar su nuevo servidor. Luego debe seleccionar un plan sobre la cantidad de recursos que desea darle a su máquina virtual. Jenkins no utiliza muchos recursos, pero Xilinx Vivado es un verdadero consumidor de RAM. Por lo tanto, debes elegir al menos el plan con 4 GB de RAM, como se muestra en la imagen a continuación.

Recomiendo echar un vistazo a la página de Recomendaciones de memoria de Xilinx porque el uso de la memoria está estrechamente relacionado con la complejidad de la FPGA de destino. La página enumera el uso máximo de memoria para la FPGA Zynq-7000 XC7Z045 que estoy usando, que es de 1,9 GB. Descubrí que el plan de 2 GB era demasiado pequeño para enrutar el diseño. Vivado falló y apareció el siguiente mensaje en el dmesg registro:

[807816.678940] Sin memoria:proceso eliminado 22605 (vivado) total-vm:2046684kB, anon-rss:782916kB, file-rss:308kB, shmem-rss:0kB

Tenga en cuenta que siempre puede actualizar fácilmente los recursos de RAM y CPU de su servidor desde su cuenta de UpCloud. No obtendrá automáticamente el espacio adicional en el disco duro que viene con los paquetes más costosos sin volver a particionar el sistema de archivos del VPS, pero se ejecutará. Como referencia, comencé con el plan con 50 GB de almacenamiento y usé el 61% de eso después de completar todo el servidor de automatización. Solo Vivado ocupa 24 GB de espacio.

Le recomiendo que seleccione la última distribución de CentOS Linux como sistema operativo, como se muestra en la imagen a continuación. Xilinx Vivado admite oficialmente sólo Red Hat Linux, que no es gratuito. Pero CentOS es una distribución de Linux gratuita y respaldada por la comunidad que sigue de cerca a Red Hat.

Luego hay algunas opciones sobre redes que puedes dejar en los valores predeterminados. También hay una sección en la página web donde puedes cargar tus claves SSH para iniciar sesión sin contraseña. Siempre puedes configurar estas cosas más adelante usando el método convencional de Linux para cargar claves SSH.

Finalmente, debe especificar el nombre de host y el nombre del servidor, como se muestra en la imagen a continuación. El nombre de host es el dominio público que los usuarios ingresarán en el navegador para acceder al servidor Jenkins. Si no tienes un dominio o subdominio listo, siempre puedes acceder al servidor usando su dirección IP. Cuando esté satisfecho con la configuración, presione el botón Implementar. para crear el servidor.

Después de haber creado el servidor, la contraseña generada automáticamente se mostrará como una notificación. Puedes cambiar esto más tarde, usando la contraseña de Linux. comando. Si proporcionó su clave SSH antes de implementar el servidor, no necesitará la contraseña en absoluto. Si alguna vez pierde el acceso a su servidor, siempre puede iniciar sesión desde su cuenta de UpCloud presionando Abrir la conexión de la consola , como se muestra en la imagen siguiente.

Configuración de zona DNS

Al nuevo servidor se le asignan direcciones IPv4 e IPv6 permanentes, que se encuentran en su cuenta de UpCloud en Servidores->Red . Puede acceder al servidor mediante SSH en la cuenta raíz de la dirección IPv4 pública.

Usando la dirección IP de ejemplo de la imagen a continuación, el comando apropiado para ingresar en su computadora doméstica con Linux sería:

Está bien usar solo la dirección IP si lo haces sólo como experimento. Pero una solución más práctica es asignar un nombre de dominio permanente al servidor. Para hacerlo, debe comprar un dominio de uno de los muchos registradores que están disponibles en línea.

Como ya poseo el dominio vhdlwhiz.com, decidí crear un subdominio para el servidor Jenkins llamado jenkins.vhdlwhiz.com . Configuramos el nombre de dominio correctamente en el servidor UpCloud cuando lo implementamos. Lo siguiente que debemos hacer es apuntar el subdominio a la dirección IPv4 pública.

La siguiente imagen muestra la configuración que estoy ingresando en el archivo de zona DNS de mi registrador de nombres de dominio. Si quisiera que el servidor estuviera en el dominio superior (vhdlwhiz.com), habría dejado el campo de nombre de host en blanco. Pero quiero que esté en el subdominio "jenkins" de vhdlwhiz.com. Por lo tanto, ingreso el nombre del subdominio.

Pasará algún tiempo después de cambiar la configuración de DNS antes de que pueda usar el nombre de dominio para acceder a su sitio web. Por lo general, no se necesitan más de 20 minutos, pero en casos extremos, los cambios pueden tardar hasta 48 horas en propagarse a todos los rincones de Internet.

Cuando los cambios hayan entrado en vigor, podrá utilizar el nombre de dominio en lugar de la dirección IP al iniciar sesión en el servidor a través de SSH:

ssh root@yoursub.yourdomain.com

Instalando Jenkins

Lo primero que debe hacer después de iniciar sesión en la cuenta raíz de su nuevo servidor Linux es actualizar todos los paquetes instalados. En CentOS Linux, yum es el administrador de paquetes predeterminado. Vamos a utilizar el yum comando para instalar la mayor parte del software.

Emita el siguiente comando para actualizar todos los paquetes instalados a las últimas versiones:

Ahora que sabemos que nuestro sistema está actualizado, podemos continuar con la instalación. Pero antes de emitir el yum comando para instalar Jenkins, instalaremos Java versión 11, explícitamente. Eso nos ahorrará algunos problemas más adelante cuando instalemos Xilinx Vivado.

Actualmente, no hay ningún intérprete de Java presente en nuestro servidor, y si le decimos a yum para instalar Jenkins, instalará la versión 8 de Java. Eso funciona bien para Jenkins, pero nos creará problemas más adelante porque Vivado depende de la versión 11 de Java.

Instale Java 11 usando este comando antes de instalar Jenkins:

yum -y install java-11-openjdk-devel

Jenkins no está disponible en el repositorio de software predeterminado que viene con CentOS. Afortunadamente, podemos importar el repositorio de Jenkins desde Red Hat usando los siguientes comandos:

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

Finalmente, podemos seguir adelante e instalar Jenkins:

El servidor Jenkins se iniciará automáticamente después del siguiente inicio, pero puede iniciar el servidor sin reiniciar así:

Siempre puedes comprobar el estado del servidor Jenkins utilizando systemctl. comando:

Imprimirá el estado del servidor junto con cualquier mensaje de error:

Jenkins sobre HTTP inseguro

En este punto, Jenkins se está ejecutando en el puerto 8080 del VPS, pero no tiene forma de conectarse con su navegador web. Esto se debe a que el firewall de CentOS bloquea el puerto 8080 y el puerto 80 (HTTP) de forma predeterminada. Lo que podemos hacer para solucionarlo es abrir el puerto 80 en el firewall y redirigirlo al puerto 8080 usando iptables. .

Pero antes de hacer eso, debes decidir si deseas proteger tu sitio con HTTPS. El problema de usar sólo HTTP y el puerto 80 es que su sitio web será inseguro. Si accede a través de una red Wi-Fi pública, una persona malintencionada conectada a la misma red Wi-Fi con una computadora portátil y un software de piratería fácilmente disponible puede espiar su conexión y robar sus credenciales de inicio de sesión en Jenkins.

Si desea evitar el riesgo de seguridad de HTTP sin cifrar, pase a la siguiente sección sobre cómo configurar HTTPS para Jenkins. De lo contrario, sigue leyendo.

Habilitar el acceso HTTP inseguro a Jenkins es tan fácil como emitir los siguientes comandos:

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

Luego puede ingresar su nombre de dominio en su navegador favorito y el Introducción de Jenkins. debería aparecer la página. Al menos en Google Chrome, se mostrará la advertencia "No seguro" en la barra de direcciones, como se muestra en la imagen a continuación.

Vaya directamente a Configuración de Jenkins sección si está satisfecho con eso.

Jenkins a través de HTTPS seguro

Tener un sitio web no seguro y accesible al público es un enorme riesgo de seguridad. Jenkins puede acceder a su código fuente, al igual que cualquier hacker que consiga acceder al servidor. Afortunadamente, proteger el sitio web está a solo unos pocos comandos de copiar y pegar.

Jenkins no puede manejar HTTPS por sí solo. Por lo tanto, tenemos que instalar un servidor web genérico para redirigir las solicitudes que llegan por el canal seguro al servidor Jenkins inseguro. Usaré Nginx, que es uno de los servidores web gratuitos y de código abierto más populares en la actualidad.

Emita el siguiente comando para instalar e iniciar Nginx:

yum -y install nginx
systemctl start nginx

Luego necesitamos abrir los puertos HTTP y HTTPS en el firewall. Solo atenderemos solicitudes HTTPS, pero también debemos mantener abierto el puerto HTTP porque configuraremos Nginx para redirigir todas las solicitudes no seguras al puerto seguro.

Estos comandos abrirán el firewall para el tráfico web:

firewall-cmd --permanent --zone=public --add-port=80/tcp
firewall-cmd --permanent --zone=public --add-port=443/tcp
firewall-cmd --reload

El siguiente paso es instalar un certificado que los navegadores web puedan usar para certificar que es su sitio web con el que están interactuando y no un impostor. Usaremos la autoridad de certificación gratuita Let's Encrypt para proteger nuestro sitio. Los pasos individuales son complicados, pero afortunadamente, certbot proporciona un script que puede hacerlo automáticamente.

Descargue y prepare el script con los siguientes comandos:

apt update
apt install snapd
snap install core; snap refresh core
snap install --classic certbot

A continuación, ejecute el script, que instalará el certificado y realizará los cambios necesarios en el archivo de configuración de Nginx:

A medida que se ejecuta el script, le solicitará información. Responda afirmativamente (Sí, Aceptar) a todas las preguntas hasta que se le solicite elegir si redirigir o no el tráfico HTTP a HTTPS. La siguiente lista muestra las preguntas y mi respuesta sugerida (2). Permitir que Nginx redirija solicitudes inseguras garantiza que nadie pueda ingresar explícitamente http:// tusitio.com y llegar a la versión insegura de Jenkins. Nginx los redireccionará a la versión segura.

...
Deploying Certificate to VirtualHost /etc/nginx/nginx.conf
 
Please choose whether or not to redirect HTTP traffic to HTTPS, removing HTTP access.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: No redirect - Make no further changes to the webserver configuration.
2: Redirect - Make all requests redirect to secure HTTPS access. Choose this for
new sites, or if you're confident your site works on HTTPS. You can undo this
change by editing your web server's configuration.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate number [1-2] then [enter] (press 'c' to cancel): 2

Finalmente, debes habilitar un trabajo cron para renovar el certificado periódicamente. De lo contrario, caducará y los navegadores se negarán a abrir su sitio.

Emita el siguiente comando de una sola línea para agregar el trabajo cron diario:

echo "0 0 * * * /snap/bin/certbot renew --quiet" | crontab -

El demonio cron ejecutará el script de renovación diariamente a medianoche. Puede enumerar los trabajos cron con crontab -l comando y editarlos con el crontab -e comando. Si visita su sitio web ahora, verá la página de prueba de Nginx, no Jenkins. Arreglaremos este problema en breve, pero asegúrese de que la advertencia "No seguro" desaparezca de la barra de direcciones de Chrome, como muestra la siguiente imagen.

Para que Nginx sirva a Jenkins, debe realizar algunos cambios en /etc/nginx/nginx.conf archivo. El crédito por este fragmento de código va al blog de Kerren en Medium. Usar el editor nano es probablemente la forma más sencilla de editar el archivo de configuración:

nano /etc/nginx/nginx.conf

Localice el bloque del servidor que enumera su nombre de dominio y agregue las líneas resaltadas del listado a continuación a su archivo nginx.conf. Tenga en cuenta que la primera de las tres líneas nuevas va por encima del bloque del servidor y el resto va al bloque de ubicación raíz.

Una vez que haya actualizado el archivo de configuración, deberá volver a cargar Nginx para que los cambios surtan efecto. Opcionalmente, puede probar el archivo de configuración antes de recargarlo usando el comando:

Nginx imprimirá OK o le dirá en qué línea del nginx.conf archivo el error es. Cuando esté satisfecho con los cambios, puede recargar el servidor web dando el siguiente comando:

Cuando visite el sitio de Jenkins en su navegador, debería ver la página de introducción de Jenkins, como se muestra en la imagen siguiente. Esta vez se realiza a través de una conexión segura y podemos continuar configurando Jenkins de forma segura desde la interfaz GUI web.

Configurar Jenkins

La primera vez que visite su sitio web de Jenkins, le solicitará una contraseña que se encuentra en un archivo del sistema de archivos de Linux. Mientras inicia sesión a través de SSH, use el siguiente comando para mostrar la contraseña. Cópielo y péguelo en el navegador para obtener acceso a la GUI web:

cat /var/lib/jenkins/secrets/initialAdminPassword

En la siguiente pantalla, Jenkins le preguntará si desea instalar los complementos sugeridos o si desea especificar cuál instalar. Simplemente vaya con Instalar complementos sugeridos opción por ahora. Siempre podrás agregar o eliminar complementos más adelante.

En la página siguiente, debe crear un usuario administrador. Complete sus datos y cree una contraseña segura para usar con su nueva cuenta. De forma predeterminada, solo los usuarios que hayan iniciado sesión pueden acceder al servidor Jenkins. Los usuarios anónimos sólo verán el cuadro de diálogo de inicio de sesión si se aventuran a visitar su sitio web. La única razón por la que puedes acceder a mi *sitio de demostración jenkins.vhdlwhiz.com es que he hecho cambios en el servidor. Utilicé el complemento Matrix Authorization Strategy para otorgar acceso anónimo a algunas vistas.

* Actualización:eliminé el sitio de demostración el 13 de mayo de 2020

Cuando Jenkins termine de instalar los complementos, verá el mensaje "¡Jenkins está listo!". mensaje, como se muestra en la imagen de arriba. Haga clic en el botón que le llevará a la página de descripción general vacía de su nueva instalación de Jenkins.

Instalación de complementos de Jenkins

Lo primero que debe hacer es instalar un montón de complementos. Jenkins tiene un administrador de complementos integrado que puede utilizar para instalar, actualizar y eliminar extensiones. Encontrará complementos que pueden satisfacer la mayoría de sus necesidades. Simplemente use la función de búsqueda en el administrador de complementos cuando necesite agregar funcionalidad a Jenkins.

Pasemos a instalar los complementos que utilicé al configurar el servidor Jenkins de ejemplo. En la barra lateral, elija Administrar Jenkins->Administrar complementos->Disponible . Tenga en cuenta que no se enumeran complementos a menos que ingrese algo en el campo de búsqueda. Una vez que escribas, aparecerán.

Océano Azul

El primer complemento que recomiendo instalar se llama Blue Ocean. Este complemento es una modernización del flujo de trabajo de Jenkins y de la interfaz de usuario. También incluye muchos otros complementos útiles para que no tengas que instalarlos individualmente. Busque "océano azul" en el administrador de complementos y selecciónelo para instalarlo, como se muestra en la imagen a continuación.

En la página de progreso de la instalación que aparece después de hacer clic en instalar, tiene la opción de seleccionar Reiniciar Jenkins cuando se complete la instalación y no se estén ejecutando trabajos . Si marca la casilla al lado, Jenkins se reiniciará una vez completada la instalación del complemento. Otra forma de reiniciar Jenkins es iniciar sesión en el servidor a través de SSH y ejecutar el siguiente comando:

systemctl restart jenkins

Aparte de la larga lista de otros complementos instalados por Blue Ocean, no hay ningún cambio notable a primera vista. Pero habrá un nuevo elemento de menú en la barra lateral, como se muestra en la imagen a continuación. Al hacer clic, accederá a la GUI de Blue Ocean, que se ve bastante diferente de la interfaz normal de Jenkins. ¡Pruébalo!

Bolas verdes

El siguiente complemento que siempre instalo es puramente estético. El complemento Green Balls no requiere ninguna configuración. Simplemente busque "bola verde" en el administrador de complementos e instálela como se muestra en la imagen a continuación.

De forma predeterminada, Jenkins usa bolas de color azul en la página de descripción general para indicar que el estado de un trabajo es exitoso. La razón tiene algo que ver con que el inventor de Jenkins es japonés. Curiosamente, en Japón, el color azul es intercambiable con el verde cuando se trata de indicar un estado OK. Más información sobre esto en este artículo, donde podrá escuchar al autor explicar el motivo de primera mano.

Los usuarios de la mayoría de otras partes del mundo probablemente preferirían las bolas de estado verdes. Esto se soluciona fácilmente con el complemento Green Balls, como se muestra en la imagen a continuación.

Complemento de configuración regional

El siguiente complemento que instalé se llama Locale. Busque "localización" en Disponible pestaña en el administrador de complementos. Instale el complemento, como se muestra en la imagen a continuación.

El complemento le permite obligar a Jenkins a utilizar el mismo idioma en la GUI para todos los usuarios. De forma predeterminada, Jenkins traduce la interfaz de usuario al idioma que utiliza su navegador web. Soy noruego, pero preferiría Jenkins en inglés. La traducción fue un poco inadecuada. Además, es mucho más fácil buscar respuestas en inglés en Google si necesitas saber cómo hacer algo en Jenkins.

Por supuesto, depende totalmente de usted si desea este complemento. Si lo instala, debe navegar hasta Administrar Jenkins->Configurar sistema y busque la sección denominada Configuración . Luego, debe ingresar “en_US” (o el idioma que desee) y marcar la casilla a continuación para forzar este idioma a todos los usuarios, como se muestra en la imagen a continuación. No olvides desplazarte hasta el final de la página y hacer clic en Guardar. .

El último complemento que necesitas para clonar mi configuración es el complemento Sidebar Link. Le permite agregar enlaces personalizados a la barra lateral de Jenkins. Lo usaremos más adelante para agregar un enlace a las versiones de FPGA (archivos de bits). Busque "barra lateral" en el administrador de complementos e instálelo, como se muestra en la imagen a continuación.

Conectar Jenkins a GitHub

Independientemente de si su repositorio es público o privado, debe otorgarle a Jenkins algunos permisos en su cuenta de GitHub. Al menos si desea hacerlo de la manera más sencilla posible, debe dejar que el complemento Jenkins GitHub administre la interfaz con GitHub por usted. Blue Ocean ya instaló el complemento GitHub. Estos son los pasos para configurarlo.

Primero, debes instalar Git en tu sistema. El complemento de GitHub no lo necesita estrictamente, pero cuando comienzas a trabajar con trabajos de Jenkins, debes tenerlo. Emita este comando para instalar Git en CentOS Linux:

Token de acceso personal en GitHub

Inicie sesión en GitHub, haga clic en su imagen de perfil en la esquina superior derecha, elija configuración y vaya a Configuración de desarrollador . Luego, elija Tokens de acceso personal en el menú de la barra lateral izquierda, o haz clic en este enlace que te llevará directamente allí.

Aquí debe hacer clic en Generar nuevo token , como se muestra en la imagen a continuación. GitHub te pedirá tu contraseña una vez más. Lo que estás haciendo ahora es esencialmente crear una nueva contraseña específica de la aplicación. Eso es mejor que compartir su contraseña real porque puede revocarla y limitar los permisos otorgados al token. Eso es lo que haremos en la página que se abre.

Cuando haya ingresado su contraseña, deberá darle un nombre al token. El nombre es sólo para ti. Puede ser cualquier cosa, "Jenkins", por ejemplo. Luego, debes habilitar al menos el admin:org_hook , admin:repo_hook y repositorio permisos, como se muestra en la imagen a continuación. Puedes dejar todas las demás casillas sin marcar.

Finalmente, cuando haces clic en Generar token , aparecerá el código de acceso. Debe copiarlo antes de salir de esa página porque no es posible volver a verlo. Si lo olvidas, elimina el token y vuelve a crearlo.

Ingresando las credenciales de GitHub en Jenkins

Cuando haya copiado el token, vaya a Jenkins, seleccione Administrar Jenkins->Configurar sistema y busque la sección denominada GitHub , como se muestra en la imagen a continuación. En el menú desplegable, seleccione Agregar Servidor GitHub->Servidor GitHub .

En la nueva sección de GitHub Server que aparece, marque la casilla denominada Administrar enlaces . Cuando hagas esto, Jenkins instalará webhooks en GitHub para los repositorios que estás monitoreando. Más adelante veremos que esto es particularmente útil porque los usaremos para activar una simulación o compilar en Jenkins cuando un usuario envía código al repositorio de GitHub asociado.

Seleccione Credenciales (Agregar)->Jenkins después de haber marcado la casilla, como se muestra en la imagen a continuación.

En la ventana que se abre, cambie el Tipo menú desplegable para Texto secreto . Luego, pega el token de acceso personal que generaste previamente en GitHub en el Secreto. campo. Escribe “GitHub” en el campo ID y presiona Agregar .

Finalmente, cuando regrese al menú de configuración principal, después de agregar el texto secreto, seleccione el nuevo GitHub. clave de Credenciales menú. Luego, presione Probar conexión para verificar que Jenkins pueda hablar con GitHub usando el token de acceso. Si todo salió bien, deberías ver un mensaje como el que se muestra en la imagen a continuación.

Asegúrate de desplazarte hasta el final de la página y hacer clic en Guardar. antes de salir de la página de configuración.

Si tiene problemas y termina agregando varias credenciales, puede eliminarlas yendo a Administrar Jenkins->Administrar usuarios. y haga clic en su nombre de usuario. Ahora, en la barra lateral izquierda, habrá un elemento de menú llamado Credenciales. . Desde allí, puede ver y editar todas las claves que Jenkins ha almacenado.

Enviando correo electrónico desde Jenkins

Vamos a configurar Jenkins para que envíe correos electrónicos automáticos cuando algo se rompa en su código. Para que eso suceda, necesitamos realizar algunos cambios en Administrar Jenkins->Configurar sistema. menú.

Lo primero que debe hacer es ingresar la dirección de origen que utilizará Jenkins al enviar correos electrónicos automatizados. Busque la dirección de correo electrónico del administrador del sistema en la página de configuración e ingrese la dirección desde la que desea que Jenkins envíe el envío.

Sólo una nota rápida:es mejor ingresar una dirección que termine con el nombre de dominio de Jenkins. Eso minimiza la posibilidad de que el correo electrónico termine en la carpeta de spam. El servidor Jenkins no tiene permiso para enviar correos electrónicos en nombre de otros dominios, pero la mayoría de los servicios de correo electrónico aceptan direcciones de origen con el mismo dominio que el servidor de envío. Lea más sobre eso en este artículo de Wikipedia. En la imagen a continuación, ingresé una dirección de origen que termina con el mismo dominio que el servidor Jenkins.

A continuación, debemos darle a Jenkins una forma de enviar correos electrónicos. La forma más sencilla de hacerlo es instalar un servidor SMTP (correo) en el VPS. Puede hacerlo iniciando sesión y emitiendo los siguientes comandos:

yum -y install sendmail
systemctl enable sendmail
systemctl restart sendmail

Después de haber instalado sendmail , regrese a la configuración del sistema Jenkins e ingrese “localhost” en el servidor SMTP campo, como se muestra en la imagen siguiente.

En este punto, también puedes marcar la casilla para permitir el envío a usuarios no registrados. Eso significa usuarios que no tienen una cuenta de usuario de Jenkins. Más adelante, configuraremos Jenkins para enviar un correo electrónico a cualquier persona que envíe código defectuoso a GitHub. Jenkins obtendrá la dirección de correo electrónico del culpable de GitHub, pero eso solo funcionará si la persona tiene una cuenta de Jenkins coincidente o si marcamos esta casilla.

Finalmente, puedes probar la configuración, como se muestra en la imagen de arriba. Después de presionar Probar configuración , debería aparecer el mensaje "El correo electrónico se envió correctamente" y el correo electrónico debería llegar a su bandeja de entrada. Revise su carpeta de spam si no recibe el correo electrónico dentro de cinco minutos.

Instalación de Xilinx Vivado en modo por lotes

Estoy usando Xilinx Vivado para simular, compilar e implementar el código en este proyecto de ejemplo. El dispositivo de destino es el FPGA Xilinx Zynq-7000 en la placa de desarrollo ZebBoard. En esta sección, le mostraré cómo instalar Vivado en el VPS usando la licencia WebPACK gratuita.

El primer paso es descargar el instalador unificado de Xilinx:instalador web autoextraíble de Linux, que se muestra en la imagen a continuación. Deberá iniciar sesión o crear una nueva cuenta Xilinx para descargar el instalador.

Cuando se haya completado la descarga, debes copiarla desde tu computadora de escritorio al servidor Jenkins. Si tiene acceso a un shell de Linux en su escritorio, le sugiero utilizar una copia segura de archivos como se muestra en el siguiente comando:

Antes de poder ejecutar el instalador, debe instalar algunos paquetes para satisfacer las dependencias de Vivado. Ejecute los siguientes comandos para hacer eso:

yum -y install tar
yum -y install java-11-openjdk-devel
yum -y install ncurses-compat-libs
yum -y install gcc

Luego, ejecute el instalador de Xilinx Unified así:

./Xilinx_Unified_2019.2_1106_2127_Lin64.bin --keep --noexec --target Xil_installer

El archivo .bin descomprimirá los archivos de instalación en un nuevo directorio llamado Xil_installer. . Si en su lugar recibe el error que aparece a continuación, es porque no ha instalado tar .

Verifying archive integrity... All good.
Uncompressing Xilinx InstallerExtraction failed.
Terminated

El instalador Xilinx Unified puede instalar muchas herramientas Xilinx diferentes en su sistema. Por lo tanto, debemos ejecutar el xsetup archivo en el Xil_installer directorio para especificar qué software nos interesa:

cd Xil_installer/
./xsetup -b ConfigGen

El xsetup El script le pregunta qué herramientas le gustaría tener. Ingrese “2” para Vivado y luego “1” para Vivado HL WebPACK , como se muestra en la siguiente lista.

Select a Product from the list:
1. Vitis
2. Vivado
3. On-Premises Install for Cloud Deployments
4. BootGen
5. Lab Edition
6. Hardware Server
7. Documentation Navigator (Standalone)
 
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

Para instalar la edición Xilinx WebPACK, debe iniciar sesión en su cuenta Xilinx durante la instalación. En una computadora de escritorio, la GUI del instalador lo guía a través de este proceso, pero en el servidor no hay GUI, por lo que tenemos que autenticarnos usando xsetup. guión. Ejecute el siguiente comando para generar el token de autenticación:

Tuve que ejecutar el comando varias veces antes de que funcionara. Al principio, el script se detuvo con el error "Conexión a Internet validada, se puede conectar a Internet". Sin embargo, después de algunos intentos, logré comunicarme y pude iniciar sesión. El script le pedirá su ID de usuario y contraseña. Ese es el correo electrónico y la contraseña que utilizó para descargar el instalador desde xilinx.com.

Finalmente, está listo para instalar Vivado en modo por lotes. Al llamar al script de instalación, debe especificar el archivo de configuración de instalación para que xsetup sabe qué herramientas descargar. El archivo de configuración está en .Xilinx carpeta en el directorio de inicio del usuario root. Ejecute el siguiente comando para iniciar la instalación usando el archivo de configuración:

./xsetup -a XilinxEULA,3rdPartyEULA,WebTalkTerms \
 -b Install -c ~/.Xilinx/install_config.txt

El proceso de instalación tardará mucho en completarse. La instalación de Vivado utiliza 24 GB de espacio. Todo eso ahora se está descargando desde el relativamente lento servidor Xilinx. A mí la descarga me llevó poco más de dos horas.

Una vez completada la instalación, debe probar que Vivado se inicie correctamente en modo por lotes. Xilinx proporciona un script de shell que configura el entorno por usted. Before you can run Vivado, you need to use the source command to load the content of the script into your active shell:

source /tools/Xilinx/Vivado/2019.2/settings64.sh

Then, you are ready to run Vivado. But there’s no GUI environment installed on your server, so we have to start it in batch mode by using this command:

If Vivado starts and exists immediately without printing any errors, it’s an indication that Vivado has everything it needs, and you are ready to go. Note that if you are getting the error listed below, it’s because you haven’t installed the ncurses-compat-libs package, as we talked about at the start of this section.

application-specific initialization failed:
couldn't load file "librdi_commontasks.so":
libtinfo.so.5: cannot open shared object file: No such file or directory

Integrating Vivado in Jenkins

To prepare Jenkins for Vivado, we need to make some changes to the general settings. Head to Manage Jenkins->Configure System and check that all the default settings make sense for you.

As I mentioned earlier, Vivado uses a lot of RAM. The resource usage depends on your target FPGA, and you can get an indication of how much you need from the Xilinx Memory Recommendations page. Therefore, I recommend that you change the default number of parallel jobs that can run from 2 to 1. Unless you allocated vast RAM resources on your VPS, you probably want to set # of executors to 1, as shown in the image below.

Instead of defining the environment variables in every Jenkins job, we will specify the PATH globally for all jobs. That makes it easier for you to swap to a newer version of Vivado in the future. Then you can refer to the ‘vivado’ executable in your scripts, and it will always point to the latest version, or whichever you decide.

Scroll to the Global properties section and check Environment variables . Click Add to get a new entry. Make sure to include the standard Linux PATH también. I used “PATH=/tools/Xilinx/Vivado/2019.2/bin:/sbin:/usr/sbin:/bin:/usr/bin”, as shown in the image below.

Don’t forget to scroll to the bottom of the page and click Save .

Vivado GUI projects in batch mode

I chose to manage the Vivado projects in GUI mode. For each repository, I created a new project from within the regular Vivado GUI, adding source files, setting libraries, and all of that. However, the .xpr project files are binary and depend on a lot of other temporary files in the project directory.

Binary files are not suitable for SCMs like Git. Fortunately, Xilinx has thought of this and written a guideline (XAPP1165) for how to use Vivado with version control systems. What we do is to use the write_project_tcl command in Vivado to export the entire project into a Tcl script. The script contains human-readable Tcl code suitable for Git.

I’ve organized all of the Git repos so that all files that belong to the Vivado projects are in a subfolder named “vivado”, while the VHDL source files are in the parent directory. Check out the demo packages project on my GitHub to see what I mean. For each repo, we will put the Vivado Tcl scripts in the vivado folder. You will also find the create_vivado_proj.tcl file, which is the human-readable version of the Vivado project.

To create the create_vivado_proj.tcl file, start by setting up the Vivado project as you wish in the Vivado GUI. Make sure that the Vivado project resides within a vivado subfolder. When you’re happy with the project, export it by entering the following commands in the Vivado Tcl console:

cd [get_property DIRECTORY [current_project]]
write_project_tcl -force -target_proj_dir . create_vivado_proj

Add the create_vivado_proj.tcl file to Git, and set up the gitignore to ignore the rest of the Vivado project. Here’s the content of my .gitignore file which ignores everything but Tcl scripts in the vivado folder:

Opening the Vivado project in batch mode

It’s a good idea to test the Vivado project manually on the VPS before you start creating Jenkins jobs. By default, the daemon runs from a user account named jenkins on the Linux server. Therefore, you should test the Vivado project using the jenkins user.

Make sure that you have Git installed on the Linux server before you start this experiment. Run this command to install Git after logging in as root:

You can’t log in to the jenkins user directly, but you can change to it from the root user like this:

If you now run a pwd command, you will see that you are at /var/lib/jenkins :

[jenkins@jenkins ~]$ pwd
/var/lib/jenkins

That’s because this isn’t a regular user account that has the home directory under /home , as is the norm on Linux systems. It’s only for running the Jenkins daemon, but we can log in to perform a manual walkthrough of the build process in the Jenkins environment.

The home folder is full of all the dynamic data like logs, user settings, and plugins that you have downloaded. When we later start running jobs in the Jenkins GUI, they will appear in the jobs folder.

Let’s go to the jobs folder to perform our experiment:

cd /var/lib/jenkins/jobs/

You can clone your Git repository directly into the jobs folder. Your Git repo has to be accessible without using a password. Either because it’s public, or because you have set up passwordless login as described on the GitHub help pages.

If you don’t have a Git repository with the Vivado project ready, feel free to clone one of my repos like this:

git clone https://github.com/jonasjj/Jenkins-demo-packages

Then, cd into the new directory of the Git repository, and further into the vivado folder:

cd Jenkins-demo-packages/vivado/

If you downloaded my example, you would find two Tcl files:create_vivado_proj.tcl and check_syntax.tcl . The first one is the Vivado project converted to a Tcl file, and the second one is a script that we haven’t talked about yet. It’s for checking the syntax of VHDL files in the Vivado project.

Before we can run any Vivado command, we need to set the PATH environment variable in the current shell. In Jenkins, we solved this by using Global properties , but now we are not coming through Jenkins, so we have to source the setup script from Xilinx like this:

source /tools/Xilinx/Vivado/2019.2/settings64.sh

Now that the vivado executable is in our path, let’s start by recreating the project. This is the command for doing that when running Vivado in batch mode:

vivado -mode batch -source create_vivado_proj.tcl

After you hit Enter, you should see a whole lot of Tcl code echoed to the console. It’s the code for recreating the Vivado project that’s executing. If you didn’t see any obvious errors, type the command “echo $?” in the terminal before you do anything else. The output should be 0 if everything went well, as we can see from the listing below.

INFO: [Common 17-206] Exiting Vivado at Sun Apr 19 18:32:48 2020...
[jenkins@jenkins vivado]$ echo $?
0

The “echo $?” command shows you the exit status from the previous command that you executed in Linux. An exit status of 0 means that everything is OK, no error. Any other exit status than 0 is an indication of error. Those are old Unix conventions that you can read more about here. Anyway, the exit status is important for Jenkins because that’s how it decides if a job stage is a success or a failure.

If you now do a directory listing, you will see that Vivado has recreated the project’s binary files:

[jenkins@jenkins vivado]# ls -la
total 72
drwxrwxr-x. 6 jenkins jenkins 4096 Apr 19 18:32 .
drwxrwxr-x. 4 jenkins jenkins 4096 Apr 19 18:18 ..
-rw-rw-r--. 1 jenkins jenkins 217 Apr 19 18:18 check_syntax.tcl
-rw-rw-r--. 1 jenkins jenkins 23375 Apr 19 18:18 create_vivado_proj.tcl
drwxrwxr-x. 3 jenkins jenkins 16 Apr 19 18:32 packages.cache
drwxrwxr-x. 2 jenkins jenkins 26 Apr 19 18:32 packages.hw
drwxrwxr-x. 2 jenkins jenkins 6 Apr 19 18:32 packages.ip_user_files
-rw-rw-r--. 1 jenkins jenkins 9314 Apr 19 18:32 packages.xpr
-rw-rw-r--. 1 jenkins jenkins 638 Apr 19 18:32 vivado.jou
-rw-rw-r--. 1 jenkins jenkins 20153 Apr 19 18:32 vivado.log
drwxrwxr-x. 2 jenkins jenkins 6 Apr 19 18:32 .Xil

Let’s try another experiment with running Tcl scripts in Vivado batch mode. Create a one-liner Tcl script by using the following command:

Now, run the script in Vivado batch mode:

vivado -mode batch -source test.tcl

After Vivado closes, check the exit code once more using the “echo $?” command:

[jenkins@jenkins vivado]# echo $?
1

It’s 1, which means exit failure in Unix. If you change the content of the test.tcl script to “exit 0”, and run Vivado once again, you will see that the exit status is now 0, indicating success. Try it!

The exit keyword is standard Tcl. We are going to use it as the interface between Vivado and Jenkins. Jenkins runs whatever Tcl script we create in Vivado, and looks at the exit status to determine if it shall mark the job stage as success or failure.

Remember to delete our little test project from the jobs folder when you are happy with the experiment:

cd /var/lib/jenkins/jobs/
[jenkins@jenkins jobs]# rm -rf Jenkins-demo-packages

Tcl script for checking code syntax in Vivado

This Tcl script runs a syntax check of the VHDL files in the project. If you are going to simulate or implement the code, you won’t need this script because any syntax errors will break the compilation. But for my packages project, it doesn’t make any sense to create a testbench for it. The files just contain constant and types declarations. I still want to catch any coding errors pushed to this repo, and that’s where the syntax check comes in handy.

In the script that is listed below, we start by opening the project file. Then, we call the Vivado check_syntax command while telling it to save the output to a variable called msg . After the check has completed, we look at the output message to see if there were any errors reported. If check_syntax reported anything at all, we set the exit status to 1 (failure). If there were no errors, we exit 0 (success).

check_syntax.tcl:

# 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 supports all of the standard Tcl keywords, and there are also a lot of built-in commands like check_syntax. I recommend taking a look at these two Xilinx documents that cover the Tcl scripting capabilities in great detail:

Vivado Design Suite Tcl Command Reference Guide (UG835)

Vivado Design Suite User Guide Using Tcl Scripting (UG894)

Tcl script for simulating in Vivado

The next script that I created is for running the testbench in batch mode. For this to work, you have to configure the simulation sets in the Vivado GUI before you export the project to Tcl. Go ahead and recreate one of the simulation projects on your desktop computer using the create_vivado_proj.tcl script to see how I set it up beforehand. You can open the reconstructed projects in the Vivado GUI.

As you can see from the listing below, I start by opening the project. Then, I set the name of the simulation fileset to a variable (usually sim_1 ). After we launch the simulation, we also have to close it. Otherwise, the status of the simulation won’t get written to the log files.

run_simulation.tcl:

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]

Now, I struggled to find a good way of getting the simulation status. My VHDL testbenches terminate on a VHDL finish keyword on success. Errors will result in a VHDL assertion failure. There’s no obvious way to find out why the simulator stopped by using Tcl commands in Vivado.

Fortunately, Tcl is a powerful scripting language. My workaround is to open the simulation log and look for the string “Failure:”, which indicates a VHDL assertion failure. Finally, we exit 1 if the word is in the log, or 0 if it isn’t.

Tcl script for synthesizing in Vivado

In the Tcl script for synthesizing in Vivado batch mode, we start by opening the project file. Then, We assign the run name to a variable. You must have added the design files to the Vivado project before you exported it to Tcl. If you didn’t change the name of the synthesis run in the GUI, it’s will probably be “synth_1”.

You should set the CPU count variable to the number of logical processors that your server has. This number controls the degree of multithreading that Vivado uses. I opted for the VPS with 4 CPUs on UpCloud, and therefore set the CPU count to 4.

run_synthesis.tcl :

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

The launch_runs command is non-blocking, meaning that it will complete before the actual synthesis. If we try to read the status right after calling launch_run , it will be “Running”. To pause the script until the synthesis completes, we call the wait_on_run command.

Finally, we get the run status and exit 0 or 1, depending on the status message.

Tcl script for running the implementation in Vivado

The script for running Place and Route (PAR) in Vivado batch mode is similar to the synthesis script. The difference is that the run name is now “impl_1”, and that we are looking for another success message.

run_implementation.tcl :

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

Tcl script for generating the bitstream in Vivado

Finally, after if the implementation completes successfully, we can generate a bitstream for programming the FPGA. The script is similar to the previous one, but the launch_runs command is slightly different. And of course, we are looking or a different status in the end.

generate_bitstream.tcl :

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

Setting up the Jenkins jobs

A job in Jenkins refers to a set of grouped software tasks. Jenkins displays jobs and their current status as items listed on the overview page. You can start jobs manually from the web interface, or they can be triggered automatically, for example, when someone pushes code to a repo, or as a result of another job completing. We will do both.

Jenkins offers several ways of managing jobs. The traditional method is the Freestyle project , where you specify every action from within the Jenkins web GUI. The more modern way of managing Jenkins jobs is to use a pipeline script that stores all of the information about the execution flow. The pipeline scripts have the benefit that you can add them to your SCM.

To create a new pipeline script, select New item from the Jenkins sidebar. In the dialog that opens, select the Pipeline option and click OK, as shown in the image below.

The first thing we have to do in the job configuration is to add the GitHub repository that contains the source code. In this example, I am using the packages repo, but the procedure is the same for all the other jobs and repos. Check the GitHub project box and enter the address in the Project url field that appears, as shown in the image below.

After that, we can set up the build triggers for this job. I want this job to start when someone pushes code to the GitHub repo. To do that, we check the box that says GitHub hook trigger for GITScm polling , as shown in the image below. Note that this will only work if you have checked the Manage hooks box in the global settings, as we did earlier.

At the bottom of the job configuration page is the Pipeline section. Here, you have to option to enter the pipeline script directly into the config page. But we want to version control the pipeline script. Therefore, we chose the Pipeline script from SCM opción. Make sure that Git is selected, as shown in the image below.

Paste in the URL of your GitHub repository, and select your credentials if it’s a private repo. Ours is public, so we will leave the credentials blank. We will also go with the default master branch selection.

Finally, we have to select the path to the Jenkins script within the Git repository. I have created a file named Jenkinsfile at the root of each repo. Don’t forget to click Save before you leave the page.

Jenkins pipeline scripts

Pipeline scripts follow the same syntax rules as the Apache Groovy programming language, which I must admit I had never heard of before. Nevertheless, you won’t have a hard time understanding pipeline scripts if you’ve done any kind of modern programming. At first glance, it looks like a JSON schema without the commas separating the data items.

The scripts are quite versatile, and there are many options for things like executing stages in parallel or running tasks on multiple Jenkins servers. I suggest that you take a look at the official Jenkins pipeline documentation if you want to dig deeper into the matter.

Fortunately, you don’t need to know everything about them to benefit from pipeline scripts. We will use the format below as a template for all of your scripts. We will add as many stages as we need to split the job into logical steps.

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'
 }
 }
}

If somebody pushes faulty code to the repo, we want the culprit to receive an automated email with information about the failed job. To do that, we use a failure section within a post section. This part of the script will only execute if any of the stages fail. Then, the job will stop. Jenkins won’t go to the next stage if one fails. Instead, it will jump into the failur e section. Jenkins then lifts the email addresses from the latest Git commits and sends them an email with a link to the broken build.

VHDL syntax checking job

The only repo in our design that doesn’t have a testbench is the packages repo—instead, we user our check_syntax.tcl script to verify that the code is at least valid VHDL.

In the first step of our pipeline script, we call deleteDir() . That’s one of the basic commands available in Jenkins pipeline scripts. It cleans the working directory by removing any leftover from previous builds.

On the next line, we call git . Note that this is not the git Linux command, but a command referencing the git Jenkins plugin. We tell it to clone the repository into the workspace.

Finally, on the third line of the Create project stage, we use the sh keyword to call a Linux shell command. Here, we change to the vivado directory and run the create_vivado_proj.tcl script in Vivado batch mode to recreate the Vivado project.

Jenkinsfile:

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'
 }
 }
}

In the second stage, the one named Check VHDL syntax , the Vivado project already exists, so we can jump to running our Tcl script. We use the shell command again to run the check_syntax.tcl file, which will exit 0 on success, or 1 on error, causing Jenkins to mark the build as a failure.

VHDL simulation jobs

For all other jobs than the packages repo, the git one-liner command won’t work for checking out the code from GitHub. The problem is that these repos have dependencies in the form of submodules. The submodules reference other Git repositories, which the simple git command doesn’t pull by default. But that’s OK; we can fix the issue by using the more versatile checkout call, also well-documented on the Git plugin page.

Jenkinsfile;

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'
 }
 }
}

Finally, we run the run_simulation.tcl script in Vivado in the next stage.

The above listing shows the script used in the bcd_encoder repo. Identical scripts, only with different repo URLs, are used for the counter, digit_selector, output_mux, reset, and seg7_encoder repos as well.

FPGA implementation job

The seg7 repo contains the top module for our FPGA project. It pulls in all of the other repos as submodules. The pipeline script is similar to the one used for the simulation-only jobs, but with four added stages:Run simulation , Run implementation , Generate bitstream , and Release bitfile .

The first two stages create the project and run the simulation. I have already covered how they work in the previous sections of this article. The next three stages work the same way as the simulation stage, but with the Tcl script replaced with the ones that are relevant for the task.

Jenkinsfile:

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'
 }
 }
}

The final stage of the implementation job is named Release bitfile . It contains a shell script that copies the newly generated FPGA programming file to a release folder. The shell command renames the file to include the name of the project and a timestamp.

To maintain traceability, we also generate a text file that contains the Git hash of the main repo (seg7 ) and all of the submodules. When working with Git submodules, it’s not enough to store the hash of the main repo. To generate a hash for the main repo that includes changes in all submodules, we would have to commit the main repo after pulling and updating all submodules. We don’t want to do that automatically from Jenkins.

Note that implementing the FPGA for every single push, like I am doing in the example, is probably not what you want for a real-life Jenkins project. It can take hours to build a large-scale FPGA project, and that wouldn’t work when you have a team of developers pushing multiple times per day. Instead of building after each push to the repo, you can configure Jenkins to route the FPGA only once a day. For example, at midnight, as shown by the screenshot below from the job configuration page.

Triggering builds after other jobs complete

Our example project consists of several Git repositories, but they are all tied together as Git submodules. Except for packages, all the other repos depend on at least one other repository. Most depend on the packages repository. Have a look at the dependency graph that I presented earlier in this article to see how it all fits together.

Therefore, we should trigger jobs not only by pushes to the repo in question but also after any of the submodules are touched. We can achieve this in Jenkins by visiting every job and setting the Build after other projects are built option accordingly.

The image below shows the trigger for the bcd_encoder project. It will start after the packages repo, which it depends on, completes a build successfully.

The top module depends on all other repos. I have added them as watch projects in a comma-separated list, as shown in the image below. Note that you may not want to do this for the FPGA implementation job if it takes a long time to route, as I mentioned in the previous section.

Serving the bitfiles using Nginx

Since we already have a web server running, we can use if for serving the release files over HTTP. I want all new bitfiles to appear on the URL jenkins.vhdlwhiz.com/releases . Let’s see how we can use Nginx for this.

Our implementation job already copies new bitfiles to a directory on the Nginx HTML root, but we haven’t created it yet. Create the release dir and give the Jenkins user write permissions by issuing the following commands:

mkdir /usr/share/nginx/html/releases/
chown jenkins.root /usr/share/nginx/html/releases/

Then we have to make a change to the /etc/nginx/nginx.conf archivo. Find the server section in the config file with a name equal to your domain. Add the following location section inside of it, directly below the root (‘/’) location section:

location ^~ /releases {
 alias /usr/share/nginx/html/releases/;
 autoindex on;
}

Finally, after you have saved the file, test the configuration file, and reload the Nginx server:

nginx -t
systemctl reload nginx

If everything worked, you should be able to list the content of the release directory, as shown in the screenshot below from Google Chrome.

To tie the Jenkins web interface to the release dir, I want to create a link to if from the Jenkins sidebar. We have already installed the Sidebar Link plugin that enables custom links in the sidebar.

The next step is to go to Manage Jenkins->Configure System and scroll down to the Additional Sidebar Links section. Here, we can specify the name and URL of the new link, as shown in the image below. The link icon field is optional. I reused one of the icons that came with the Jenkins server.

After completing the previous step, you should now have a custom link to the bitfile releases in the sidebar, complete with a nice-looking folder icon, as you can see from the image below.

Resumen

Jenkins can be a valuable tool also for FPGA teams. Automating tasks can save your company time and improve the quality of your code. By using automatic build triggers and automated job pipelines, fewer coding errors will go unnoticed.

As we have seen from the example project presented in this article, Jenkins can implement a complete suite of regression tests for your VHDL code. It shows the current health of your project in a pleasant graphical web interface, suitable for even the most VHDL-illiterate project manager.

If you wish to try out Jenkins for FPGA development, I recommend following the steps in this article on an UpCloud VPS instance. I thoroughly researched all VPS providers a few years ago before moving VHDLwhiz to a VPS. I found that UpCloud was the fastest and best alternative. I’m still 100% pleased with the service.

If you decide to open an account on UpCloud, I kindly ask that you use my referral link or code:NV78V6 . Not only do you support VHDLwhiz, but you also get $25 of credit on UpCloud when using the promo code.


VHDL

  1. Controlador de pantalla dual VHDL de 7 segmentos para Pmod SSD:fácil integración con FPGA
  2. Cómo instalar un simulador y editor VHDL gratis
  3. Tutorial:su primer programa FPGA:un LED intermitente
  4. Cómo crear un controlador PWM en VHDL
  5. Curso FPGA – Todo lo que necesitas saber sobre el Curso Dot Matrix VHDL
  6. Archivo de estímulo leído en el banco de pruebas usando TEXTIO
  7. Cómo retrasar el tiempo en VHDL:Esperar
  8. Servocontrolador RC usando PWM desde un pin FPGA
  9. Cómo crear una declaración concurrente en VHDL
  10. Verificación aleatoria restringida
  11. Cómo usar una instrucción Case-When en VHDL