Automatisez le développement FPGA avec Jenkins, Vivado et GitHub sur un VPS Linux
* Cet article contient un lien publicitaire pour UpCloud VPS
La livraison continue et l'intégration continue sont des méthodologies de développement logiciel agiles qui raccourcissent le temps de cycle entre la modification du code et le déploiement. En utilisant l'automatisation pour vérifier les modifications du code et créer les fichiers de version, les équipes peuvent devenir plus productives et efficaces.
Les éditeurs de logiciels pratiquent le développement continu depuis longtemps, mais vous pouvez tout aussi bien utiliser ces méthodes pour vos projets FPGA. Ce didacticiel vous apprend à configurer un serveur d'automatisation sur un serveur privé virtuel (VPS) à l'aide de Jenkins, Xilinx Vivado et du système de gestion de contrôle de source (SCM) Git/GitHub.
Qu'est-ce que Jenkins ?
Le serveur d'automatisation Jenkins est un programme gratuit et open source écrit en Java. Il fonctionne sous Windows ou Linux. Nous utiliserons Linux dans cet article de blog car c'est la plate-forme la plus courante pour les serveurs sans tête.
Jenkins s'exécute en tant que processus démon sous Linux ou en tant que service sous Windows. Un serveur Web intégré que Jenkins lance au démarrage fournit l'interface utilisateur. La plupart des utilisateurs interagiront avec Jenkins en utilisant l'interface Web. Vous pouvez ajouter de nouveaux projets d'automatisation et gérer ceux existants via l'interface graphique Web.
L'image ci-dessus montre la page principale du serveur Jenkins que nous allons mettre en place aujourd'hui. Par défaut, seuls les utilisateurs connectés peuvent accéder à Jenkins, mais pour cet article, j'ai activé l'accès public à certaines parties de mon serveur *demo.
* Mise à jour :j'ai supprimé le serveur de démonstration le 13 mai 2020
Ce que vous voyez sur la page principale est une liste d'emplois. Ces tâches peuvent contenir n'importe quelle tâche et peuvent être déclenchées manuellement à partir de l'interface graphique Web. Ils peuvent également être déclenchés automatiquement via des scripts, des webhooks ou à la suite de l'exécution d'autres tâches. D'où le terme serveur d'automatisation .
Dans notre exemple, chaque tâche correspond à un module VHDL conservé dans un référentiel GitHub distinct. Nous demanderons à Jenkins d'exécuter une simulation et de construire le projet chaque fois qu'un développeur transmettra du code à l'un des dépôts Git surveillés. Si un banc de test échoue ou si la build échoue, Jenkins marquera le travail comme ayant échoué dans l'interface Web et enverra automatiquement un e-mail à la personne qui a commis le code défectueux.
L'exemple de projet
Les serveurs d'automatisation sont particulièrement utiles pour les équipes travaillant sur des projets plus importants. Par conséquent, j'ai construit un exemple de projet FPGA composé de huit référentiels Git. Le projet est le compteur d'affichage à 7 segments du cours Fast-Track porté sur le Xilinx ZedBoard.
Liens vers les huit dépôts sur GitHub :
- forfaits (Paquets VHDL)
- bcd_encoder (Module)
- compteur (Module)
- digit_selector (Module)
- output_mux (Module)
- réinitialiser (Module)
- seg7_encoder (Module)
- seg7 (Module supérieur)
Chaque dépôt contient un module VHDL et son banc de test. Une exception concerne les packages repo, qui ne contient que trois packages VHDL définissant des constantes et des types. De plus, le seg7 Le module supérieur contient un fichier de contraintes qui définit la vitesse d'horloge et les affectations de broches de l'implémentation physique.
La plupart des projets VHDL à grande échelle utilisent des modules provenant de plusieurs référentiels. Les entreprises disposent généralement d’une bibliothèque de packages et de modules qu’elles réutilisent dans de nombreuses conceptions. C'est ce que j'imite en divisant cette conception plutôt simple en autant de modules.
Dans notre exemple, tous les modules dépendent du dépôt de packages, et le module supérieur dépend également de tous les sous-modules. J'ai résolu ce problème en les important selon les besoins à l'aide de sous-modules Git standard. Le graphique ci-dessus montre le contenu et les dépendances de tous les dépôts de ce projet.
Les référentiels Git contiennent également plusieurs fichiers non liés à la conception, tels que la configuration Jenkins et les scripts de build. Nous en parlerons dans les prochaines sections de cet article.
Serveur privé virtuel (VPS)
Bien que Jenkins puisse fonctionner sur n'importe quel ordinateur Windows ou Linux, à toutes fins pratiques, vous souhaiterez l'exécuter sur un serveur dédié. Le serveur d'automatisation doit être toujours opérationnel et accessible à tous les membres de votre équipe. Si vous disposez d’un serveur physique avec une capacité suffisante, c’est parfait. Mais pour la plupart d'entre nous, une solution plus rapide et moins coûteuse consiste à utiliser un serveur privé virtuel (VPS).
Un VPS est un ordinateur virtuel que vous louez auprès d’un hébergeur sur Internet. Il apparaît comme un véritable ordinateur Windows ou Linux avec lequel vous pouvez interagir et installer le logiciel de votre choix. Nous allons utiliser un ordinateur Linux car c'est ce qui est le plus logique pour notre cas d'utilisation.
Le site VHDLwhiz fonctionne sur un VPS, comme c'est le cas depuis deux ans. J'ai déjà eu la peine de trouver le fournisseur VPS le plus rapide et le meilleur, à savoir UpCloud. Naturellement, nous allons utiliser UpCloud pour configurer le VPS de notre serveur d'automatisation.
Obtenez le bonus UpCloud de 25 $
Si vous souhaitez essayer UpCloud, j'ai un code de parrainage qui vous donnera un crédit d'une valeur de 25 $ lors de votre inscription.
>> Cliquez ici pour obtenir le bonus UpCloud de 25 $ <<
Ou utilisez mon code promotionnel lors du paiement :NV78V6
En utilisant le code, vous obtiendrez le bonus et supporterez VHDLwhiz en même temps. Je peux obtenir des fonds crédités sur mon compte UpCloud pour chaque client qui l'utilise.
Bon, assez de discours de vente. Passons à la configuration du serveur.
Déployer le VPS UpCloud
Après vous être connecté à votre nouveau compte UpCloud, vous pouvez démarrer le processus de création d'une nouvelle instance VPS en accédant à Serveurs → Déployer le serveur .
UpCloud possède de nombreux centres de données dans le monde. Sélectionnez l'emplacement le plus proche de chez vous pour héberger votre nouveau serveur. Ensuite, vous devez sélectionner un plan indiquant la quantité de ressources à accorder à votre machine virtuelle. Jenkins n'utilise pas beaucoup de ressources, mais Xilinx Vivado est un véritable gourmand en RAM. Par conséquent, vous devez choisir au moins le forfait avec 4 Go de RAM, comme indiqué dans l'image ci-dessous.
Je recommande de jeter un œil à la page Recommandations de mémoire de Xilinx car l'utilisation de la mémoire est étroitement liée à la complexité du FPGA cible. La page indique que l'utilisation maximale de la mémoire pour le FPGA Zynq-7000 XC7Z045 que j'utilise est de 1,9 Go. J'ai trouvé que le forfait 2 Go était trop peu pour router le design. Vivado a planté et le message suivant est apparu dans le dmesg journal :
[807816.678940] Mémoire insuffisante :processus arrêté 22605 (vivado) total-vm : 2046684 ko, anon-rss : 782916 ko, file-rss : 308 ko, shmem-rss : 0 ko
Notez que vous pouvez toujours mettre à niveau facilement les ressources RAM et CPU de votre serveur depuis votre compte UpCloud. Vous n’obtiendrez pas automatiquement l’espace disque supplémentaire fourni avec les packages les plus coûteux sans repartitionner le système de fichiers du VPS, mais il fonctionnera. Pour référence, j'ai commencé avec le plan avec 50 Go de stockage, et j'en ai utilisé 61 % après avoir terminé l'intégralité du serveur d'automatisation. Vivado occupe à lui seul 24 Go d'espace.
Je vous recommande de sélectionner la dernière distribution CentOS Linux comme système d'exploitation, comme indiqué dans l'image ci-dessous. Xilinx Vivado ne prend officiellement en charge que Red Hat Linux, qui n'est pas gratuit. Mais CentOS est une distribution Linux gratuite et soutenue par la communauté qui suit de près Red Hat.
Ensuite, il existe certaines options concernant la mise en réseau que vous pouvez laisser par défaut. Il existe également une section sur la page Web où vous pouvez télécharger vos clés SSH pour une connexion sans mot de passe. Vous pourrez toujours configurer ces éléments ultérieurement en utilisant la méthode Linux conventionnelle pour télécharger les clés SSH.
Enfin, vous devez spécifier le nom d'hôte et le nom du serveur, comme indiqué dans l'image ci-dessous. Le nom d'hôte est le domaine public que les utilisateurs entreront dans le navigateur pour accéder au serveur Jenkins. Si vous n'avez pas de domaine ou de sous-domaine prêt, vous pouvez toujours accéder au serveur en utilisant son adresse IP. Lorsque vous êtes satisfait des paramètres, appuyez sur le bouton Déployer. bouton pour créer le serveur.
Après avoir créé le serveur, le mot de passe généré automatiquement s'affichera sous forme de notification. Vous pourrez modifier cela plus tard, en utilisant le passwd de Linux. commande. Si vous avez fourni votre clé SSH avant de déployer le serveur, vous n'aurez pas du tout besoin du mot de passe. Si jamais vous perdez l'accès à votre serveur, vous pouvez toujours vous connecter depuis votre compte UpCloud en appuyant sur Ouvrir la connexion à la console. , comme le montre l'image ci-dessous.
Paramètres des zones DNS
Le nouveau serveur se voit attribuer des adresses IPv4 et IPv6 permanentes, trouvées dans votre compte UpCloud sous Serveurs->Réseau . Vous pouvez accéder au serveur en utilisant SSH sur le compte root de l'adresse IPv4 publique.
En utilisant l'exemple d'adresse IP de l'image ci-dessous, la commande appropriée à saisir sur votre ordinateur personnel Linux serait :
Vous pouvez utiliser uniquement l’adresse IP si vous le faites simplement à titre expérimental. Mais une solution plus pratique consiste à attribuer un nom de domaine permanent au serveur. Pour ce faire, vous devez acheter un domaine auprès de l'un des nombreux bureaux d'enregistrement disponibles en ligne.
Comme je possède déjà le domaine vhdlwhiz.com, j'ai décidé de créer un sous-domaine pour le serveur Jenkins nommé jenkins.vhdlwhiz.com. . Nous avons correctement configuré le nom de domaine sur le serveur UpCloud lorsque nous l'avons déployé. La prochaine chose que nous devons faire est de faire pointer le sous-domaine vers l'adresse IPv4 publique.
L'image ci-dessous montre les paramètres que je saisis dans le fichier de zone DNS de mon registraire de nom de domaine. Si je voulais que le serveur soit sur le domaine principal (vhdlwhiz.com), j'aurais laissé le champ du nom d'hôte vide. Mais je veux que ce soit sur le sous-domaine « jenkins » de vhdlwhiz.com. Par conséquent, j'entre le nom du sous-domaine.
Il faudra un certain temps après la modification des paramètres DNS avant que vous puissiez utiliser le nom de domaine pour accéder à votre site Web. Habituellement, cela ne prend pas plus de 20 minutes, mais dans des cas extrêmes, cela peut prendre jusqu'à 48 heures pour que les modifications se propagent à tous les coins d'Internet.
Une fois les modifications entrées en vigueur, vous pouvez utiliser le nom de domaine au lieu de l'adresse IP lors de la connexion au serveur via SSH :
ssh root@yoursub.yourdomain.com
Installer Jenkins
La première chose à faire après vous être connecté au compte root sur votre nouveau serveur Linux est de mettre à jour tous les packages installés. Sous CentOS Linux, miam est le gestionnaire de paquets par défaut. Nous allons utiliser le miam commande pour installer la plupart des logiciels.
Exécutez la commande suivante pour mettre à jour tous les packages installés vers les dernières versions :
Maintenant que nous savons que notre système est à jour, nous pouvons procéder à l'installation. Mais avant de lancer le miam commande pour installer Jenkins, nous allons installer Java version 11, explicitement. Cela nous évitera des ennuis plus tard lorsque nous installerons Xilinx Vivado.
Actuellement, il n'y a aucun interpréteur Java présent sur notre serveur, et si on le dit miam pour installer Jenkins, il va installer Java version 8. Cela fonctionne bien pour Jenkins, mais cela nous créera des problèmes plus tard car Vivado dépend de Java version 11.
Installez Java 11 à l'aide de cette commande avant d'installer Jenkins :
yum -y install java-11-openjdk-devel
Jenkins n'est pas disponible dans le référentiel de logiciels par défaut fourni avec CentOS. Heureusement, nous pouvons importer le dépôt Jenkins depuis Red Hat en utilisant les commandes suivantes :
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
Enfin, nous pouvons continuer et installer Jenkins :
Le serveur Jenkins démarrera automatiquement après le prochain démarrage, mais vous pouvez démarrer le serveur sans redémarrer comme ceci :
Vous pouvez toujours vérifier l'état du serveur Jenkins en utilisant le systemctl commande :
Il affichera l'état du serveur ainsi que les éventuels messages d'erreur :
Jenkins sur HTTP non sécurisé
À ce stade, Jenkins fonctionne sur le port 8080 du VPS, mais vous n'avez aucun moyen de vous y connecter avec votre navigateur Web. En effet, le pare-feu CentOS bloque par défaut le port 8080 et le port 80 (HTTP). Ce que nous pouvons faire pour résoudre ce problème, c'est ouvrir le port 80 dans le pare-feu et le rediriger vers le port 8080 à l'aide de iptables. .
Mais avant de faire cela, vous devez décider si vous souhaitez sécuriser votre site avec HTTPS. Le problème en utilisant uniquement HTTP et le port 80 est que votre site Web ne sera pas sécurisé. Si vous y accédez via un réseau Wi-Fi public, une personne malveillante utilisant le même réseau Wi-Fi avec un ordinateur portable et un logiciel de piratage facilement disponible peut écouter votre connexion et voler vos identifiants de connexion à Jenkins.
Si vous souhaitez éviter le risque de sécurité lié au HTTP non chiffré, passez à la section suivante sur la configuration du HTTPS pour Jenkins. Sinon, continuez à lire.
Activer un accès HTTP non sécurisé à Jenkins est aussi simple que d'émettre les commandes suivantes :
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
Ensuite, vous pouvez saisir votre nom de domaine dans votre navigateur préféré et le Mise en route de Jenkins. la page devrait apparaître. Au moins dans Google Chrome, l'avertissement « Non sécurisé » s'affichera dans la barre d'adresse, comme le montre l'image ci-dessous.
Passez directement à la Configuration de Jenkins. section si cela vous convient.
Jenkins sur HTTPS sécurisé
Avoir un site Web non sécurisé accessible au public représente un risque de sécurité énorme. Jenkins peut accéder à votre code source, tout comme tout pirate informatique qui parvient à s'introduire dans le serveur. Heureusement, il suffit de copier-coller quelques commandes pour sécuriser le site Web.
Jenkins ne peut pas gérer HTTPS seul. Par conséquent, nous devons installer un serveur Web générique pour rediriger les requêtes arrivant via le canal sécurisé vers le serveur Jenkins non sécurisé. J'utiliserai Nginx, qui est l'un des serveurs Web gratuits et open source les plus populaires aujourd'hui.
Exécutez la commande suivante pour installer et démarrer Nginx :
yum -y install nginx systemctl start nginx
Ensuite, nous devons ouvrir les ports HTTP et HTTPS dans le pare-feu. Nous ne traiterons que les requêtes HTTPS, mais nous devons également garder le port HTTP ouvert car nous configurerons Nginx pour rediriger toutes les requêtes non sécurisées vers le port sécurisé.
Ces commandes ouvriront le pare-feu pour le trafic Web :
firewall-cmd --permanent --zone=public --add-port=80/tcp firewall-cmd --permanent --zone=public --add-port=443/tcp firewall-cmd --reload
L’étape suivante consiste à installer un certificat que les navigateurs Web peuvent utiliser pour certifier qu’il s’agit bien de votre site Web avec lequel ils interagissent et non d’un imposteur. Nous allons utiliser l’autorité de certification gratuite Let’s Encrypt pour sécuriser notre site. Les étapes individuelles sont compliquées, mais heureusement, certbot fournit un script qui peut le faire automatiquement pour nous.
Téléchargez et préparez le script avec les commandes suivantes :
apt update apt install snapd snap install core; snap refresh core snap install --classic certbot
Ensuite, exécutez le script qui installera le certificat et apportera les modifications nécessaires au fichier de configuration Nginx :
Au fur et à mesure que le script s'exécute, il vous demandera des informations. Répondez par l'affirmative (Oui, Accepter) à toutes les questions jusqu'à ce qu'on vous demande de choisir de rediriger ou non le trafic HTTP vers HTTPS. La liste ci-dessous montre les questions et ma réponse suggérée (2). Autoriser Nginx à rediriger les requêtes non sécurisées garantit que personne ne peut entrer explicitement http:// votresite.com et accédez à la version non sécurisée de Jenkins. Nginx les redirigera vers la version sécurisée.
... 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
Enfin, vous devez activer une tâche cron pour renouveler périodiquement le certificat. Sinon, il expirera et les navigateurs refuseront complètement d'ouvrir votre site.
Exécutez la commande simple suivante pour ajouter la tâche cron quotidienne :
echo "0 0 * * * /snap/bin/certbot renew --quiet" | crontab -
Le démon cron exécutera le script de renouvellement quotidiennement à minuit. Vous pouvez lister les tâches cron avec crontab -l commande et éditez-les avec crontab -e commande. Si vous visitez votre site Web maintenant, vous verrez la page de test Nginx, et non Jenkins. Nous allons résoudre ce problème sous peu, mais assurez-vous que l'avertissement « Non sécurisé » a disparu de la barre d'adresse de Chrome, comme le montre l'image ci-dessous.
Pour que Nginx serve Jenkins, vous devez apporter quelques modifications au /etc/nginx/nginx.conf fichier. Le mérite de cet extrait de code revient au blog de Kerren sur Medium. Utiliser l'éditeur nano est probablement le moyen le plus simple de modifier le fichier de configuration :
nano /etc/nginx/nginx.conf
Localisez le bloc de serveur qui répertorie votre nom de domaine et ajoutez les lignes en surbrillance de la liste ci-dessous à votre fichier nginx.conf. Notez que la première des trois nouvelles lignes va au-dessus du bloc serveur et le reste va dans le bloc d'emplacement racine.
Après avoir mis à jour le fichier de configuration, vous devez recharger Nginx pour que les modifications prennent effet. Facultativement, vous pouvez tester le fichier de configuration avant de recharger en utilisant la commande :
Nginx affichera OK ou vous indiquera sur quelle ligne du nginx.conf fichier l'erreur est. Lorsque vous êtes satisfait des modifications, vous pouvez recharger le serveur Web en donnant la commande suivante :
Lorsque vous visitez maintenant le site Jenkins dans votre navigateur, vous devriez voir la page de démarrage de Jenkins, comme le montre l'image ci-dessous. Cette fois, il est servi via une connexion sécurisée, et nous pouvons continuer en toute sécurité à configurer Jenkins depuis l'interface graphique Web.
Configurer Jenkins
La première fois que vous visitez votre site Web Jenkins, il vous demandera un mot de passe trouvé dans un fichier du système de fichiers Linux. Une fois connecté via SSH, utilisez la commande ci-dessous pour afficher le mot de passe. Copiez-collez-le dans le navigateur pour accéder à l'interface graphique Web :
cat /var/lib/jenkins/secrets/initialAdminPassword
Sur l'écran suivant, Jenkins vous demandera si vous souhaitez installer les plugins suggérés ou si vous souhaitez spécifier lesquels installer. Allez simplement avec l'option Installer les plugins suggérés option pour l'instant. Vous pourrez toujours ajouter ou supprimer des plugins plus tard.
Sur la page suivante, vous devez créer un utilisateur administrateur. Remplissez vos coordonnées et créez un mot de passe fort à utiliser avec votre nouveau compte. Par défaut, seuls les utilisateurs connectés peuvent accéder au serveur Jenkins. Les utilisateurs anonymes ne verront la boîte de dialogue de connexion que s'ils s'aventurent sur votre site Web. La seule raison pour laquelle vous pouvez accéder à mon *site de démonstration jenkins.vhdlwhiz.com c'est que j'ai apporté des modifications au serveur. J'ai utilisé le plugin Matrix Authorization Strategy pour accorder un accès anonyme à certaines vues.
* Mise à jour :j'ai supprimé le site de démonstration le 13 mai 2020
Lorsque Jenkins a fini d'installer les plugins, vous verrez le message « Jenkins est prêt ! message, comme le montre l’image ci-dessus. Cliquez sur le bouton qui vous amènera à la page de présentation vide de votre nouvelle installation Jenkins.
Installation des plugins Jenkins
La première chose à faire est d’installer un tas de plugins. Jenkins dispose d'un gestionnaire de plugins intégré que vous pouvez utiliser pour installer, mettre à jour et supprimer des extensions. Vous trouverez des plugins capables de répondre à la plupart de vos besoins. Utilisez simplement la fonction de recherche dans le gestionnaire de plugins lorsque vous devez ajouter des fonctionnalités à Jenkins.
Passons à l'installation des plugins que j'ai utilisés lors de la configuration de l'exemple de serveur Jenkins. Dans la barre latérale, choisissez Gérer Jenkins->Gérer les plugins->Disponible . Notez qu'aucun plugin n'est répertorié sauf si vous saisissez quelque chose dans le champ de recherche. Une fois que vous aurez tapé, ils apparaîtront.
Océan bleu
Le premier plugin que je recommande d’installer s’appelle Blue Ocean. Ce plugin est une modernisation du workflow Jenkins ainsi que de l'interface utilisateur. Il intègre également de nombreux autres plugins utiles afin que vous n'ayez pas à les installer individuellement. Recherchez « océan bleu » dans le gestionnaire de plugins et sélectionnez-le pour l'installation, comme indiqué dans l'image ci-dessous.
Sur la page de progression de l'installation qui apparaît après avoir cliqué sur installer, vous avez la possibilité de sélectionner Redémarrer Jenkins lorsque l'installation est terminée et qu'aucune tâche n'est en cours d'exécution . Si vous cochez la case à côté, Jenkins redémarrera une fois l'installation du plugin terminée. Une autre façon de redémarrer Jenkins consiste à vous connecter au serveur via SSH et à exécuter la commande suivante :
systemctl restart jenkins
Hormis la longue liste d’autres plugins installés par Blue Ocean, il n’y a aucun changement notable à première vue. Mais il y aura un nouvel élément de menu dans la barre latérale, comme le montre l'image ci-dessous. Lorsque vous cliquez dessus, vous accédez à l'interface graphique Blue Ocean, qui est assez différente de l'interface Normal Jenkins. Essayez-le !
Boules vertes
Le prochain plugin que j’installe toujours est purement esthétique. Le plugin Green Balls ne nécessite aucune configuration. Recherchez simplement « boule verte » dans le gestionnaire de plugins et installez-le comme indiqué dans l'image ci-dessous.
Par défaut, Jenkins utilise des boules de couleur bleue dans la page de présentation pour indiquer que le statut d'une tâche est réussi. La raison a quelque chose à voir avec le fait que l’inventeur de Jenkins est japonais. Il est intéressant de noter qu’au Japon, la couleur bleue est interchangeable avec le vert lorsqu’il s’agit d’indiquer un statut OK. Plus d'informations à ce sujet dans cet article, où vous pourrez entendre l'auteur expliquer la raison de première main.
Les utilisateurs de la plupart des autres régions du monde préféreraient probablement les boules de statut vertes. Ce problème est facilement résolu par le plugin Green Balls, comme le montre l'image ci-dessous.
Plugin de localisation
Le prochain plugin que j'ai installé s'appelle Locale. Recherchez « locale » sous Disponible onglet dans le gestionnaire de plugins. Installez le plugin, comme indiqué dans l'image ci-dessous.
Le plugin vous permet de forcer Jenkins à utiliser la même langue dans l'interface graphique pour tous les utilisateurs. Par défaut, Jenkins traduit l'interface utilisateur dans la langue utilisée par votre navigateur Web. Je suis norvégien, mais je préférerais avoir Jenkins en anglais. La traduction était un peu insuffisante. De plus, il est beaucoup plus facile de rechercher des réponses en anglais sur Google si vous avez besoin de savoir comment faire quelque chose dans Jenkins.
Bien sûr, c’est à vous de décider si vous souhaitez ce plugin. Si vous l'installez, vous devez accéder à Gérer Jenkins->Configurer le système et recherchez la section nommée Locale . Ensuite, vous devez saisir « en_US » (ou la langue de votre choix) et cocher la case ci-dessous pour forcer cette langue à tous les utilisateurs, comme le montre l'image ci-dessous. N'oubliez pas de faire défiler la page jusqu'en bas et de cliquer sur Enregistrer. .
Le dernier plugin dont vous avez besoin pour cloner ma configuration est le plugin Sidebar Link. Il vous permet d'ajouter des liens personnalisés à la barre latérale Jenkins. Nous l'utiliserons plus tard pour ajouter un lien vers les versions FPGA (bitfiles). Recherchez « barre latérale » dans le gestionnaire de plugins et installez le plugin, comme indiqué dans l'image ci-dessous.
Connecter Jenkins à GitHub
Que votre référentiel soit public ou privé, vous devez accorder à Jenkins certaines autorisations sur votre compte GitHub. Au moins si vous souhaitez le faire de la manière la plus simple possible, vous devez laisser le plugin Jenkins GitHub gérer l'interface avec GitHub pour vous. Blue Ocean a déjà installé le plugin GitHub. Voici les étapes pour le configurer.
Tout d’abord, vous devez installer Git sur votre système. Le plugin GitHub n'en a pas strictement besoin, mais lorsque vous commencez à travailler avec des tâches Jenkins, vous devez l'avoir. Exécutez cette commande pour installer Git dans CentOS Linux :
Jeton d'accès personnel dans GitHub
Connectez-vous à GitHub, cliquez sur votre photo de profil dans le coin supérieur droit, choisissez les paramètres et accédez à Paramètres du développeur. . Ensuite, choisissez Jetons d'accès personnels dans le menu latéral de gauche, ou cliquez sur ce lien qui vous y mènera directement.
Ici, vous devez cliquer sur Générer un nouveau jeton , comme le montre l'image ci-dessous. GitHub vous demandera à nouveau votre mot de passe. Ce que vous faites maintenant consiste essentiellement à créer un nouveau mot de passe spécifique à l'application. C'est mieux que de partager votre mot de passe réel, car vous pouvez le révoquer et limiter les autorisations accordées au jeton. C'est ce que nous ferons sur la page qui s'ouvre.
Lorsque vous avez saisi votre mot de passe, vous devez donner un nom au token. Le nom est juste pour vous. Cela peut être n'importe quoi, « Jenkins », par exemple. Ensuite, vous devez activer au moins le admin:org_hook , admin:repo_hook , et dépôt autorisations, comme indiqué dans l’image ci-dessous. Vous pouvez laisser toutes les autres cases décochées.
Enfin, lorsque vous cliquez sur Générer un jeton , le code d'accès apparaîtra. Vous devez le copier avant de quitter cette page car il n’est pas possible de le revoir. Si vous l'oubliez, supprimez le jeton et recréez-le.
Saisie des identifiants GitHub dans Jenkins
Lorsque vous avez copié le jeton, accédez à Jenkins, sélectionnez Gérer Jenkins->Configurer le système , et recherchez la section nommée GitHub , comme le montre l'image ci-dessous. Dans le menu déroulant, sélectionnez Ajouter un Serveur GitHub->Serveur GitHub .
Dans la nouvelle section GitHub Server qui apparaît, cochez la case intitulée Gérer les hooks . Lorsque vous faites cela, Jenkins installera des webhooks sur GitHub pour les dépôts que vous surveillez. Nous verrons plus tard que cela est particulièrement utile car nous les utiliserons pour déclencher une simulation ou un build dans Jenkins lorsqu'un utilisateur pousse du code vers le dépôt GitHub associé.
Sélectionnez Identifiants (Ajouter) -> Jenkins après avoir coché la case, comme indiqué dans l'image ci-dessous.
Dans la fenêtre qui s'ouvre, modifiez le Kind liste déroulante vers Texte secret . Ensuite, collez le jeton d'accès personnel que vous avez généré précédemment dans GitHub dans le champ Secret. champ. Écrivez « GitHub » dans le champ ID et appuyez sur Ajouter .
Enfin, lorsque vous êtes de retour dans le menu de configuration principal, après avoir ajouté le texte secret, sélectionnez le nouveau GitHub clé à partir des Identifiants menu. Ensuite, appuyez sur Tester la connexion pour vérifier que Jenkins peut parler à GitHub à l'aide du jeton d'accès. Si tout s'est bien passé, vous devriez voir un message comme celui affiché dans l'image ci-dessous.
Assurez-vous de faire défiler la page jusqu'en bas et cliquez sur Enregistrer. avant de quitter la page de configuration.
Si vous rencontrez des problèmes et finissez par ajouter plusieurs informations d'identification, vous pouvez les supprimer en accédant à Gérer Jenkins->Gérer les utilisateurs. , puis cliquez sur votre nom d'utilisateur. Désormais, dans la barre latérale gauche, il y aura un élément de menu nommé Identifiants. . À partir de là, vous pouvez afficher et modifier toutes les clés stockées par Jenkins.
Envoi d'un e-mail de Jenkins
Nous allons configurer Jenkins pour qu'il envoie des e-mails automatisés lorsque quelque chose tombe en panne dans votre code. Pour y parvenir, nous devons apporter quelques modifications dans Gérer Jenkins->Configurer le système. menu.
La première chose à faire est de saisir l'adresse d'expéditeur que Jenkins utilisera lors de l'envoi d'e-mails automatisés. Recherchez l'adresse e-mail de l'administrateur système sur la page de configuration et entrez l'adresse à partir de laquelle vous souhaitez que Jenkins envoie.
Juste un petit mot :il est préférable de saisir une adresse qui se termine par le nom de domaine Jenkins. Cela minimise le risque que l'e-mail se retrouve dans le dossier spam. Le serveur Jenkins n'est pas autorisé à envoyer des e-mails au nom d'autres domaines, mais la plupart des services de messagerie acceptent les adresses d'expéditeur avec le même domaine que le serveur d'envoi. Apprenez-en davantage à ce sujet dans cet article Wikipédia. Dans l'image ci-dessous, j'ai saisi une adresse d'expéditeur se terminant par le même domaine que le serveur Jenkins.
Ensuite, nous devons donner à Jenkins un moyen d'envoyer des e-mails. Le moyen le plus simple de procéder consiste à installer un serveur SMTP (mail) sur le VPS. Vous pouvez le faire en vous connectant et en exécutant les commandes suivantes :
yum -y install sendmail systemctl enable sendmail systemctl restart sendmail
Après avoir installé sendmail , revenez à la configuration du système Jenkins et saisissez « localhost » dans le serveur SMTP champ, comme le montre l'image ci-dessous.
À ce stade, vous pouvez également cocher la case pour autoriser l'envoi aux utilisateurs non enregistrés. Cela signifie les utilisateurs qui n'ont pas de compte utilisateur Jenkins. Plus tard, nous configurerons Jenkins pour qu'il envoie un e-mail à toute personne qui transmet un code défectueux à GitHub. Jenkins obtiendra l'adresse e-mail du coupable depuis GitHub, mais cela ne fonctionnera que si la personne possède un compte Jenkins correspondant, ou si nous cochons cette case.
Enfin, vous pouvez tester la configuration, comme indiqué dans l'image ci-dessus. Après avoir appuyé sur Tester la configuration , le message « L'e-mail a été envoyé avec succès » devrait apparaître et l'e-mail devrait arriver dans votre boîte de réception. Vérifiez votre dossier spam si vous ne recevez pas l'e-mail dans les cinq minutes.
Installer Xilinx Vivado en mode batch
J'utilise Xilinx Vivado pour simuler, compiler et implémenter le code dans cet exemple de projet. Le périphérique cible est le FPGA Xilinx Zynq-7000 sur la carte de développement ZebBoard. Dans cette section, je vais vous montrer comment installer Vivado sur le VPS en utilisant la licence gratuite WebPACK.
La première étape consiste à télécharger le programme d'installation unifié Xilinx :programme d'installation Web auto-extractible Linux, illustré dans l'image ci-dessous. Vous devrez vous connecter ou créer un nouveau compte Xilinx pour télécharger le programme d'installation.
Une fois le téléchargement terminé, vous devez le copier depuis votre ordinateur de bureau vers le serveur Jenkins. Si vous avez accès à un shell Linux sur votre bureau, je vous suggère d'utiliser la copie sécurisée de fichiers comme dans la commande suivante :
Avant de pouvoir exécuter le programme d'installation, vous devez installer quelques packages pour satisfaire les dépendances de Vivado. Exécutez les commandes suivantes pour ce faire :
yum -y install tar yum -y install java-11-openjdk-devel yum -y install ncurses-compat-libs yum -y install gcc
Ensuite, exécutez le programme d'installation unifié de Xilinx comme ceci :
./Xilinx_Unified_2019.2_1106_2127_Lin64.bin --keep --noexec --target Xil_installer
Le fichier .bin décompressera les fichiers d'installation dans un nouveau répertoire nommé Xil_installer . Si vous obtenez l'erreur ci-dessous, c'est parce que vous n'avez pas installé tar. .
Verifying archive integrity... All good. Uncompressing Xilinx InstallerExtraction failed. Terminated
Le programme d'installation unifié de Xilinx peut installer de nombreux outils Xilinx différents sur votre système. Par conséquent, nous devons exécuter le xsetup fichier dans le Xil_installer répertoire pour préciser quel logiciel nous intéresse :
cd Xil_installer/ ./xsetup -b ConfigGen
Le xsetup Le script vous demande quels outils vous aimeriez avoir. Saisissez « 2 » pour Vivado , puis « 1 » pour Vivado HL WebPACK , comme indiqué dans la liste ci-dessous.
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
Pour installer l'édition Xilinx WebPACK, vous devez vous connecter à votre compte Xilinx lors de l'installation. Sur un ordinateur de bureau, l'interface graphique du programme d'installation vous guide tout au long de ce processus, mais sur le serveur, il n'y a pas d'interface graphique, nous devons donc nous authentifier en utilisant xsetup. scénario. Exécutez la commande suivante pour générer le jeton d'authentification :
J'ai dû exécuter la commande plusieurs fois avant qu'elle ne fonctionne. Au début, le script s'est arrêté avec l'erreur « Connexion Internet validée, peut se connecter à Internet ». Cependant, après quelques essais, j'ai réussi et j'ai pu me connecter. Le script vous demandera votre identifiant et votre mot de passe. Il s'agit de l'e-mail et du mot de passe que vous avez utilisés pour télécharger le programme d'installation depuis xilinx.com.
Enfin, vous êtes prêt à installer Vivado en mode batch. Lors de l'appel du script d'installation, vous devez spécifier le fichier de configuration d'installation afin que xsetup sait quels outils télécharger. Le fichier de configuration se trouve dans le .Xilinx dossier dans le répertoire personnel de l'utilisateur root. Exécutez la commande suivante pour démarrer l'installation à l'aide du fichier de configuration :
./xsetup -a XilinxEULA,3rdPartyEULA,WebTalkTerms \ -b Install -c ~/.Xilinx/install_config.txt
Le processus d’installation prendra beaucoup de temps. L'installation Vivado utilise 24 Go d'espace. Tout cela est maintenant téléchargé depuis le serveur Xilinx, relativement lent. Pour moi, le téléchargement a pris un peu plus de deux heures.
Une fois l'installation terminée, vous devez tester que Vivado démarre correctement en mode batch. Xilinx fournit un script shell qui configure l'environnement pour vous. Avant de pouvoir exécuter Vivado, vous devez utiliser la 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 aussi. 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 rubrique. 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 option. 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 rubrique. 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 file. 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 rubrique. 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.
Résumé
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
- Comment afficher les variables VHDL dans Modelsim pendant la simulation
- Comment créer une FIFO AXI dans un bloc de RAM à l'aide de la poignée de main prête/valide
- Vérification aléatoire contrainte
- Premiers pas avec VUnit
- Quiz VHDL de base – partie 1
- Fichier de stimulation lu dans testbench à l'aide de TEXTIO
- Comment créer une minuterie en VHDL
- Comment créer un processus cadencé en VHDL
- Comment utiliser Wait On et Wait Until en VHDL