Industrielle Fertigung
Industrielles Internet der Dinge | Industrielle Materialien | Gerätewartung und Reparatur | Industrielle Programmierung |
home  MfgRobots >> Industrielle Fertigung >  >> Industrial programming >> VHDL

Automatisieren Sie die FPGA-Entwicklung mit Jenkins, Vivado und GitHub auf einem Linux-VPS

* Dieser Artikel enthält einen Werbelink für UpCloud VPS

Continuous Delivery und Continuous Integration sind agile Softwareentwicklungsmethoden, die die Zykluszeit zwischen Codeänderung und Bereitstellung verkürzen. Durch den Einsatz von Automatisierung zur Überprüfung von Codeänderungen und zum Erstellen von Releasedateien können Teams produktiver und effizienter werden.

Softwareunternehmen praktizieren die kontinuierliche Entwicklung schon seit langem, aber Sie können die Methoden genauso gut für Ihre FPGA-Projekte nutzen. In diesem Tutorial erfahren Sie, wie Sie mit Jenkins, Xilinx Vivado und dem Git/GitHub-Source-Control-Management-System (SCM) einen Automatisierungsserver auf einem Virtual Private Server (VPS) einrichten.

Was ist Jenkins?

Der Jenkins-Automatisierungsserver ist ein kostenloses Open-Source-Programm, das in Java geschrieben ist. Es läuft unter Windows oder Linux. Wir werden in diesem Blogbeitrag Linux verwenden, da dies die gängigste Plattform für Headless-Server ist.

Jenkins läuft als Daemon-Prozess unter Linux oder als Dienst unter Windows. Ein integrierter Webserver, den Jenkins beim Start startet, stellt die Benutzeroberfläche bereit. Die meisten Benutzer interagieren mit Jenkins über die Weboberfläche. Über die Web-GUI können Sie neue Automatisierungsprojekte hinzufügen und bestehende verwalten.

Das Bild oben zeigt die Hauptseite des Jenkins-Servers, den wir heute einrichten werden. Standardmäßig können nur angemeldete Benutzer auf Jenkins zugreifen, aber für diesen Artikel habe ich den öffentlichen Zugriff auf Teile meines *Demoservers aktiviert.

* Update:Ich habe den Demoserver am 13. Mai 2020 heruntergefahren

Was Sie auf der Hauptseite sehen, ist eine Liste von Jobs. Diese Jobs können beliebige Aufgaben enthalten und können manuell über die Web-GUI ausgelöst werden. Oder sie können automatisch durch Skripte, Webhooks oder als Ergebnis der Ausführung anderer Jobs ausgelöst werden. Daher der Begriff Automatisierungsserver .

In unserem Beispiel entspricht jeder Job einem VHDL-Modul, das in einem separaten GitHub-Repository gespeichert ist. Wir lassen Jenkins eine Simulation ausführen und das Projekt erstellen, wann immer ein Entwickler Code an eines der überwachten Git-Repos sendet. Wenn eine Testbench fehlschlägt oder der Build fehlschlägt, markiert Jenkins den Job in der Weboberfläche als fehlgeschlagen und sendet automatisch eine E-Mail an die Person, die den fehlerhaften Code begangen hat.

Das Beispielprojekt

Automatisierungsserver sind am nützlichsten für Teams, die an größeren Projekten arbeiten. Deshalb habe ich ein Beispiel-FPGA-Projekt erstellt, das aus acht Git-Repositorys besteht. Das Projekt ist der 7-Segment-Anzeigezähler aus dem Fast-Track-Kurs, portiert auf das Xilinx ZedBoard.

Links zu den acht Repos auf GitHub:

Jedes Repo enthält ein VHDL-Modul und seine Testbench. Eine Ausnahme bilden die Pakete Repo, das nur drei VHDL-Pakete enthält, die Konstanten und Typen definieren. Zusätzlich das seg7 Das obere Modul enthält eine Einschränkungsdatei, die die Taktrate und Pinbelegungen der physischen Implementierung definiert.

Die meisten großen VHDL-Projekte verwenden Module aus mehr als einem Repository. Unternehmen verfügen in der Regel über eine Bibliothek mit Paketen und Modulen, die sie in vielen Designs wiederverwenden. Das ist es, was ich nachahme, indem ich dieses eher einfache Design in so viele Module aufteile.

In unserem Beispiel sind alle Module vom Paket-Repo abhängig, und das oberste Modul hängt auch von allen Untermodulen ab. Ich habe dieses Problem gelöst, indem ich sie nach Bedarf mithilfe von Standard-Git-Submodulen importierte. Die obige Grafik zeigt den Inhalt und die Abhängigkeiten aller Repos in diesem Projekt.

Die Git-Repositorys enthalten auch mehrere Nicht-Design-Dateien, etwa die Jenkins-Konfiguration und Build-Skripte. Wir werden in den kommenden Abschnitten dieses Artikels darüber sprechen.

Virtueller privater Server (VPS)

Während Jenkins auf jedem Windows- oder Linux-Computer ausgeführt werden kann, sollten Sie es aus praktischen Gründen auf einem dedizierten Server ausführen. Der Automatisierungsserver muss immer betriebsbereit und für alle Ihre Teammitglieder zugänglich sein. Wenn Sie einen physischen Server mit ausreichend Kapazität haben, ist das großartig. Für die meisten von uns ist die Verwendung eines virtuellen privaten Servers (VPS) jedoch eine schnellere und kostengünstigere Lösung.

Ein VPS ist ein virtueller Computer, den Sie über das Internet von einem Hosting-Unternehmen mieten. Es erscheint wie ein echter Windows- oder Linux-Computer, mit dem Sie interagieren und jede gewünschte Software installieren können. Wir werden einen Linux-Computer verwenden, da dies für unseren Anwendungsfall am sinnvollsten ist.

Die VHDLwhiz-Site läuft wie schon seit zwei Jahren auf einem VPS. Ich habe mir bereits die Mühe gemacht, den schnellsten und besten VPS-Anbieter zu finden, nämlich UpCloud. Natürlich werden wir UpCloud verwenden, um den VPS für unseren Automatisierungsserver einzurichten.

Holen Sie sich den UpCloud-Bonus von 25 $

Wenn Sie UpCloud ausprobieren möchten, habe ich einen Empfehlungscode, mit dem Sie ein Guthaben im Wert von 25 $ erhalten bei der Anmeldung.

>> Klicken Sie hier, um den UpCloud-Bonus von 25 $ zu erhalten <<

Oder verwenden Sie beim Bezahlvorgang meinen Aktionscode:NV78V6

Durch die Verwendung des Codes erhalten Sie den Bonus und unterstützen gleichzeitig VHDLwhiz. Es kann sein, dass mir für jeden Kunden, der es nutzt, etwas Geld auf mein UpCloud-Konto gutgeschrieben wird.

Okay, genug mit dem Verkaufsgespräch. Fahren wir mit der Einrichtung des Servers fort.

Bereitstellung des UpCloud VPS

Nachdem Sie sich bei Ihrem neuen UpCloud-Konto angemeldet haben, können Sie mit der Erstellung einer neuen VPS-Instanz beginnen, indem Sie zu Server → Server bereitstellen navigieren .

UpCloud verfügt über viele Rechenzentren auf der ganzen Welt. Wählen Sie den Standort aus, der Ihnen am nächsten liegt, um Ihren neuen Server zu hosten. Anschließend müssen Sie einen Plan auswählen, wie viele Ressourcen Sie Ihrer virtuellen Maschine zur Verfügung stellen möchten. Jenkins verbraucht nicht viele Ressourcen, aber Xilinx Vivado ist ein echter RAM-Fresser. Daher sollten Sie mindestens den Plan mit 4 GB RAM wählen, wie im Bild unten gezeigt.

Ich empfehle einen Blick auf die Seite „Speicherempfehlungen“ von Xilinx, da die Speichernutzung eng mit der Komplexität des Ziel-FPGA zusammenhängt. Auf der Seite wird die maximale Speichernutzung für den von mir verwendeten Zynq-7000 XC7Z045 FPGA mit 1,9 GB aufgeführt. Ich fand, dass der 2-GB-Plan für das Routing des Designs zu wenig war. Vivado stürzte ab und die folgende Meldung erschien im dmesg log:

[807816.678940] Nicht genügend Arbeitsspeicher:Prozess 22605 (vivado) total-vm:2046684kB, anon-rss:782916kB, file-rss:308kB, shmem-rss:0kB beendet

Beachten Sie, dass Sie die RAM- und CPU-Ressourcen Ihres Servers jederzeit problemlos über Ihr UpCloud-Konto aktualisieren können. Sie erhalten nicht automatisch den zusätzlichen Festplattenspeicher, der mit den teureren Paketen einhergeht, ohne das Dateisystem des VPS neu zu partitionieren, aber es wird ausgeführt. Als Referenz:Ich habe mit dem Plan mit 50 GB Speicher begonnen und nach Fertigstellung des gesamten Automatisierungsservers 61 % davon genutzt. Allein Vivado benötigt 24 GB Speicherplatz.

Ich empfehle Ihnen, als Betriebssystem die neueste CentOS-Linux-Distribution auszuwählen, wie im Bild unten gezeigt. Xilinx Vivado unterstützt offiziell nur Red Hat Linux, das nicht kostenlos ist. Aber CentOS ist eine kostenlose, von der Community unterstützte Linux-Distribution, die Red Hat sehr nahe kommt.

Dann gibt es einige Optionen zum Netzwerk, die Sie auf den Standardeinstellungen belassen können. Es gibt auch einen Abschnitt auf der Webseite, in dem Sie Ihre SSH-Schlüssel für die passwortlose Anmeldung hochladen können. Sie können diese Dinge später jederzeit mit der herkömmlichen Linux-Methode zum Hochladen von SSH-Schlüsseln konfigurieren.

Abschließend müssen Sie den Hostnamen und den Namen des Servers angeben, wie im Bild unten gezeigt. Der Hostname ist die öffentliche Domäne, die Benutzer in den Browser eingeben, um auf den Jenkins-Server zuzugreifen. Wenn Sie keine Domain oder Subdomain bereit haben, können Sie jederzeit über seine IP-Adresse auf den Server zugreifen. Wenn Sie mit den Einstellungen zufrieden sind, klicken Sie auf Bereitstellen Klicken Sie auf die Schaltfläche, um den Server zu erstellen.

Nachdem Sie den Server erstellt haben, wird das automatisch generierte Passwort als Benachrichtigung angezeigt. Sie können dies später mit dem Linux-passwd ändern Befehl. Wenn Sie Ihren SSH-Schlüssel vor der Bereitstellung des Servers angegeben haben, benötigen Sie das Passwort überhaupt nicht. Sollten Sie jemals den Zugriff auf Ihren Server verlieren, können Sie sich jederzeit von Ihrem UpCloud-Konto aus anmelden, indem Sie auf Konsolenverbindung öffnen klicken , wie im Bild unten gezeigt.

DNS-Zoneneinstellungen

Dem neuen Server werden permanente IPv4- und IPv6-Adressen zugewiesen, die Sie in Ihrem UpCloud-Konto unter Server->Netzwerk finden . Sie können auf den Server zugreifen, indem Sie eine SSH-Verbindung zum Root-Konto der öffentlichen IPv4-Adresse herstellen.

Wenn Sie die Beispiel-IP-Adresse aus dem Bild unten verwenden, wäre der entsprechende Befehl, den Sie auf Ihrem Linux-Heimcomputer eingeben müssen:

Es ist in Ordnung, nur die IP-Adresse zu verwenden, wenn Sie dies nur als Experiment durchführen. Eine praktischere Lösung besteht jedoch darin, dem Server einen dauerhaften Domänennamen zuzuweisen. Dazu müssen Sie eine Domain bei einem der vielen online verfügbaren Registrare erwerben.

Da ich bereits die Domäne vhdlwhiz.com besitze, habe ich beschlossen, eine Subdomäne für den Jenkins-Server mit dem Namen jenkins.vhdlwhiz.com zu erstellen . Wir haben den Domänennamen bei der Bereitstellung auf dem UpCloud-Server korrekt eingerichtet. Als nächstes müssen wir die Subdomain auf die öffentliche IPv4-Adresse verweisen.

Das Bild unten zeigt die Einstellungen, die ich in die DNS-Zonendatei meines Domainnamen-Registrators eingebe. Wenn ich wollte, dass sich der Server in der obersten Domäne (vhdlwhiz.com) befindet, hätte ich das Feld „Hostname“ leer gelassen. Aber ich möchte, dass es auf der Subdomain „jenkins“ von vhdlwhiz.com liegt. Daher gebe ich den Namen der Subdomain ein.

Nach der Änderung der DNS-Einstellungen wird es einige Zeit dauern, bis Sie über den Domainnamen auf Ihre Website zugreifen können. Normalerweise dauert es nicht länger als 20 Minuten, aber in extremen Fällen kann es bis zu 48 Stunden dauern, bis sich die Änderungen in allen Teilen des Internets verbreiten.

Wenn die Änderungen wirksam werden, können Sie beim Anmelden am Server über SSH den Domänennamen anstelle der IP-Adresse verwenden:

ssh root@yoursub.yourdomain.com

Jenkins installieren

Nachdem Sie sich beim Root-Konto auf Ihrem neuen Linux-Server angemeldet haben, sollten Sie zunächst alle installierten Pakete aktualisieren. In CentOS Linux, lecker ist der Standardpaketmanager. Wir werden das yum verwenden Befehl zum Installieren der meisten Software.

Geben Sie den folgenden Befehl ein, um alle installierten Pakete auf die neuesten Versionen zu aktualisieren:

Da wir nun wissen, dass unser System auf dem neuesten Stand ist, können wir mit der Installation fortfahren. Aber bevor wir das yum herausgeben Wenn wir den Befehl zum Installieren von Jenkins ausführen, installieren wir explizit Java Version 11. Das wird uns später einige Probleme ersparen, wenn wir Xilinx Vivado installieren.

Derzeit ist auf unserem Server kein Java-Interpreter vorhanden, und wenn wir yum sagen Um Jenkins zu installieren, wird Java Version 8 installiert. Das funktioniert gut für Jenkins, wird uns aber später Probleme bereiten, da Vivado auf Java Version 11 angewiesen ist.

Installieren Sie Java 11 mit diesem Befehl, bevor Sie Jenkins installieren:

yum -y install java-11-openjdk-devel

Jenkins ist im Standard-Software-Repository von CentOS nicht verfügbar. Glücklicherweise können wir das Jenkins-Repository mit den folgenden Befehlen von Red Hat importieren:

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

Schließlich können wir mit der Installation von Jenkins fortfahren:

Der Jenkins-Server wird nach dem nächsten Start automatisch gestartet, Sie können den Server jedoch auch ohne Neustart wie folgt starten:

Sie können den Status des Jenkins-Servers jederzeit mithilfe von systemctl überprüfen Befehl:

Der Status des Servers wird zusammen mit etwaigen Fehlermeldungen ausgedruckt:

Jenkins über unsicheres HTTP

Zu diesem Zeitpunkt läuft Jenkins auf Port 8080 auf dem VPS, Sie haben jedoch keine Möglichkeit, mit Ihrem Webbrowser eine Verbindung herzustellen. Das liegt daran, dass die CentOS-Firewall standardmäßig Port 8080 und Port 80 (HTTP) blockiert. Um das Problem zu beheben, öffnen wir Port 80 in der Firewall und leiten ihn mithilfe von iptables auf Port 8080 um .

Aber bevor Sie das tun, müssen Sie entscheiden, ob Sie Ihre Website mit HTTPS sichern möchten. Wenn Sie nur HTTP und Port 80 verwenden, besteht das Problem darin, dass Ihre Website unsicher ist. Wenn Sie über öffentliches WLAN darauf zugreifen, kann eine böswillige Person im selben WLAN mit einem Laptop und leicht verfügbarer Hacking-Software Ihre Verbindung abhören und Ihre Anmeldedaten für Jenkins stehlen.

Wenn Sie das Sicherheitsrisiko von unverschlüsseltem HTTP vermeiden möchten, fahren Sie mit dem nächsten Abschnitt über die Einrichtung von HTTPS für Jenkins fort. Ansonsten lesen Sie weiter.

Das Aktivieren des unsicheren HTTP-Zugriffs auf Jenkins ist so einfach wie die Ausgabe der folgenden Befehle:

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

Anschließend können Sie Ihren Domainnamen in Ihrem Lieblingsbrowser eingeben und die Erste Schritte von Jenkins aufrufen Seite sollte erscheinen. Zumindest in Google Chrome wird die Warnung „Nicht sicher“ in der Adressleiste angezeigt, wie im Bild unten gezeigt.

Fahren Sie mit dem Abschnitt Jenkins einrichten fort Abschnitt, wenn Sie damit zufrieden sind.

Jenkins über sicheres HTTPS

Eine ungesicherte Website, die für die Öffentlichkeit zugänglich ist, stellt ein großes Sicherheitsrisiko dar. Jenkins kann auf Ihren Quellcode zugreifen, ebenso wie jeder Hacker, der erfolgreich in den Server eindringt. Glücklicherweise ist die Sicherung der Website nur ein paar kopierte und eingefügte Befehle entfernt.

Jenkins kann HTTPS nicht alleine verarbeiten. Daher müssen wir einen generischen Webserver installieren, um Anfragen, die über den sicheren Kanal eingehen, an den unsicheren Jenkins-Server umzuleiten. Ich werde Nginx verwenden, einen der derzeit beliebtesten kostenlosen und Open-Source-Webserver.

Geben Sie den folgenden Befehl ein, um Nginx zu installieren und zu starten:

yum -y install nginx
systemctl start nginx

Dann müssen wir sowohl die HTTP- als auch die HTTPS-Ports in der Firewall öffnen. Wir werden nur HTTPS-Anfragen bedienen, müssen aber auch den HTTP-Port offen halten, da wir Nginx so konfigurieren, dass alle unsicheren Anfragen an den sicheren Port umgeleitet werden.

Diese Befehle öffnen die Firewall für den Webverkehr:

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

Der nächste Schritt besteht darin, ein Zertifikat zu installieren, mit dem Webbrowser bestätigen können, dass es sich um Ihre Website handelt, mit der sie interagieren, und nicht um einen Betrüger. Wir werden die kostenlose Zertifizierungsstelle Let’s Encrypt verwenden, um unsere Website zu sichern. Die einzelnen Schritte sind kompliziert, aber glücklicherweise stellt certbot ein Skript zur Verfügung, das dies automatisch für uns erledigen kann.

Laden Sie das Skript herunter und bereiten Sie es mit den folgenden Befehlen vor:

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

Führen Sie als Nächstes das Skript aus, das das Zertifikat installiert und die erforderlichen Änderungen an der Nginx-Konfigurationsdatei vornimmt:

Während das Skript ausgeführt wird, werden Sie zur Eingabe von Informationen aufgefordert. Beantworten Sie alle Fragen mit „Ja, Akzeptieren“, bis Sie gefragt werden, ob der HTTP-Verkehr auf HTTPS umgeleitet werden soll oder nicht. Die folgende Auflistung zeigt die Fragen und meine vorgeschlagene Antwort (2). Indem Nginx erlaubt wird, unsichere Anfragen umzuleiten, wird sichergestellt, dass niemand explizit http:// eingeben kann yoursite.com und gelangen Sie zur unsicheren Version von Jenkins. Nginx leitet sie zur sicheren Version weiter.

...
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

Abschließend sollten Sie einen Cronjob aktivieren, um das Zertifikat regelmäßig zu erneuern. Andernfalls läuft es ab und Browser weigern sich, Ihre Website überhaupt zu öffnen.

Geben Sie den folgenden einzeiligen Befehl ein, um den täglichen Cron-Job hinzuzufügen:

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

Der Cron-Daemon führt das Erneuerungsskript täglich um Mitternacht aus. Sie können die Cron-Jobs mit dem crontab -l auflisten Befehl und bearbeiten Sie sie mit crontab -e Befehl. Wenn Sie jetzt Ihre Website besuchen, sehen Sie die Nginx-Testseite und nicht Jenkins. Wir werden das Problem in Kürze beheben. Stellen Sie jedoch sicher, dass die Warnung „Nicht sicher“ aus der Chrome-Adressleiste verschwunden ist, wie das Bild unten zeigt.

Damit Nginx Jenkins bedienen kann, müssen Sie einige Änderungen an /etc/nginx/nginx.conf vornehmen Datei. Der Dank für dieses Code-Snippet geht an Kerrens Blog auf Medium. Die Verwendung des Nano-Editors ist wahrscheinlich die einfachste Möglichkeit, die Konfigurationsdatei zu bearbeiten:

nano /etc/nginx/nginx.conf

Suchen Sie den Serverblock, der Ihren Domainnamen auflistet, und fügen Sie die hervorgehobenen Zeilen aus der Liste unten zu Ihrer nginx.conf-Datei hinzu. Beachten Sie, dass die erste der drei neuen Zeilen oberhalb des Serverblocks verläuft und der Rest in den Root-Location-Block geht.

Nachdem Sie die Konfigurationsdatei aktualisiert haben, müssen Sie Nginx neu laden, damit die Änderungen wirksam werden. Optional können Sie die Konfigurationsdatei vor dem Neuladen testen, indem Sie den folgenden Befehl verwenden:

Nginx gibt OK aus oder teilt Ihnen mit, in welcher Zeile in der nginx.conf Datei der Fehler ist. Wenn Sie mit den Änderungen zufrieden sind, können Sie den Webserver neu laden, indem Sie den folgenden Befehl eingeben:

Wenn Sie nun die Jenkins-Site in Ihrem Browser besuchen, sollte die Seite „Erste Schritte“ von Jenkins angezeigt werden, wie im Bild unten dargestellt. Diesmal erfolgt die Bereitstellung über eine sichere Verbindung, und wir können Jenkins sicher über die Web-GUI-Schnittstelle weiter konfigurieren.

Jenkins einrichten

Wenn Sie Ihre Jenkins-Website zum ersten Mal besuchen, werden Sie zur Eingabe eines Passworts aufgefordert, das in einer Datei im Linux-Dateisystem gefunden wird. Während Sie über SSH angemeldet sind, verwenden Sie den folgenden Befehl, um das Passwort anzuzeigen. Kopieren Sie es und fügen Sie es in den Browser ein, um Zugriff auf die Web-GUI zu erhalten:

cat /var/lib/jenkins/secrets/initialAdminPassword

Auf dem nächsten Bildschirm fragt Jenkins Sie, ob Sie die vorgeschlagenen Plugins installieren möchten oder ob Sie angeben möchten, welche Plugins installiert werden sollen. Gehen Sie einfach zu Vorgeschlagene Plugins installieren Option für jetzt. Sie können Plugins jederzeit später hinzufügen oder entfernen.

Auf der nächsten Seite müssen Sie einen Admin-Benutzer erstellen. Geben Sie Ihre Daten ein und erstellen Sie ein sicheres Passwort, das Sie mit Ihrem neuen Konto verwenden können. Standardmäßig können nur angemeldete Benutzer auf den Jenkins-Server zugreifen. Anonyme Benutzer sehen den Anmeldedialog nur, wenn sie Ihre Website besuchen. Der einzige Grund, warum Sie auf meine *Demoseite jenkins.vhdlwhiz.com zugreifen konnten liegt daran, dass ich Änderungen am Server vorgenommen habe. Ich habe das Matrix Authorization Strategy-Plugin verwendet, um anonymen Zugriff auf einige Ansichten zu gewähren.

* Update:Ich habe die Demoseite am 13. Mai 2020 geschlossen

Wenn Jenkins mit der Installation der Plugins fertig ist, wird die Meldung „Jenkins ist bereit!“ angezeigt. Nachricht, wie im Bild oben gezeigt. Klicken Sie auf die Schaltfläche, die Sie zur leeren Übersichtsseite Ihrer neuen Jenkins-Installation führt.

Jenkins-Plugins installieren

Als Erstes müssen Sie eine Reihe von Plugins installieren. Jenkins verfügt über einen integrierten Plugin-Manager, den Sie zum Installieren, Aktualisieren und Entfernen von Erweiterungen verwenden können. Sie werden Plugins finden, die die meisten Ihrer Anforderungen erfüllen können. Verwenden Sie einfach die Suchfunktion im Plugin-Manager, wenn Sie Funktionen zu Jenkins hinzufügen müssen.

Fahren wir mit der Installation der Plugins fort, die ich beim Einrichten des Beispiel-Jenkins-Servers verwendet habe. Wählen Sie in der Seitenleiste Jenkins verwalten -> Plugins verwalten -> Verfügbar . Beachten Sie, dass keine Plugins aufgeführt werden, es sei denn, Sie geben etwas in das Suchfeld ein. Sobald Sie etwas eingeben, werden sie angezeigt.

Blauer Ozean

Das erste Plugin, das ich zur Installation empfehle, heißt Blue Ocean. Dieses Plugin ist eine Modernisierung des Jenkins-Workflows sowie der Benutzeroberfläche. Es integriert außerdem eine Reihe weiterer nützlicher Plugins, sodass Sie diese nicht einzeln installieren müssen. Suchen Sie im Plugin-Manager nach „Blue Ocean“ und wählen Sie es zur Installation aus, wie im Bild unten gezeigt.

Auf der Installationsfortschrittsseite, die angezeigt wird, nachdem Sie auf „Installieren“ geklickt haben, haben Sie die Möglichkeit, Jenkins neu starten, wenn die Installation abgeschlossen ist und keine Jobs ausgeführt werden auszuwählen . Wenn Sie das Kontrollkästchen daneben aktivieren, wird Jenkins nach Abschluss der Plugin-Installation neu gestartet. Eine andere Möglichkeit, Jenkins neu zu starten, besteht darin, sich über SSH beim Server anzumelden und den folgenden Befehl auszuführen:

systemctl restart jenkins

Abgesehen von der langen Liste weiterer Plugins, die von Blue Ocean installiert wurden, ist auf den ersten Blick keine auffällige Änderung erkennbar. In der Seitenleiste wird es jedoch einen neuen Menüpunkt geben, wie im Bild unten gezeigt. Wenn Sie darauf klicken, gelangen Sie zur Blue Ocean-GUI, die ganz anders aussieht als die normale Jenkins-Oberfläche. Probieren Sie es aus!

Grüne Kugeln

Das nächste Plugin, das ich immer installiere, dient rein ästhetischen Zwecken. Das Green Balls-Plugin erfordert keine Konfiguration. Suchen Sie einfach im Plugin-Manager nach „Green Ball“ und installieren Sie es wie im Bild unten gezeigt.

Standardmäßig verwendet Jenkins auf der Übersichtsseite blaue Farbbälle, um anzuzeigen, dass der Status eines Jobs erfolgreich ist. Der Grund liegt darin, dass der Erfinder von Jenkins Japaner ist. Interessanterweise ist in Japan die Farbe Blau mit Grün austauschbar, wenn es darum geht, einen OK-Status anzuzeigen. Mehr dazu in diesem Artikel, wo Sie dem Autor aus erster Hand den Grund erklären können.

Benutzer aus den meisten anderen Teilen der Welt würden wahrscheinlich grüne Statusbälle bevorzugen. Das lässt sich leicht mit dem Green Balls-Plugin beheben, wie im Bild unten gezeigt.

Gebietsschema-Plugin

Das nächste Plugin, das ich installiert habe, heißt Locale. Suchen Sie unter Verfügbar nach „locale“. Registerkarte im Plugin-Manager. Installieren Sie das Plugin, wie im Bild unten gezeigt.

Mit dem Plugin können Sie Jenkins dazu zwingen, für alle Benutzer dieselbe Sprache in der GUI zu verwenden. Standardmäßig übersetzt Jenkins die Benutzeroberfläche in die Sprache, die Ihr Webbrowser verwendet. Ich bin Norweger, aber ich hätte Jenkins lieber auf Englisch. Die Übersetzung war etwas unzureichend. Außerdem ist es viel einfacher, bei Google nach Antworten auf Englisch zu suchen, wenn Sie herausfinden möchten, wie man etwas in Jenkins macht.

Es liegt natürlich ganz bei Ihnen, ob Sie dieses Plugin möchten. Wenn Sie es installieren, müssen Sie zu Manage Jenkins->Configure System navigieren und suchen Sie den Abschnitt mit dem Namen Locale . Dann müssen Sie „en_US“ (oder eine beliebige Sprache) eingeben und das Kontrollkästchen unten aktivieren, um diese Sprache für alle Benutzer zu erzwingen, wie im Bild unten gezeigt. Vergessen Sie nicht, zum Ende der Seite zu scrollen und auf Speichern zu klicken .

Das letzte Plugin, das Sie zum Klonen meines Setups benötigen, ist das Sidebar Link-Plugin. Damit können Sie benutzerdefinierte Links zur Jenkins-Seitenleiste hinzufügen. Wir werden es später verwenden, um einen Link zu den FPGA-Releases (Bitdateien) hinzuzufügen. Suchen Sie im Plugin-Manager nach „sidebar“ und installieren Sie das Plugin, wie im Bild unten gezeigt.

Jenkins mit GitHub verbinden

Unabhängig davon, ob Ihr Repository öffentlich oder privat ist, müssen Sie Jenkins einige Berechtigungen für Ihr GitHub-Konto erteilen. Zumindest wenn Sie es möglichst einfach machen möchten, sollten Sie das Jenkins GitHub-Plugin die Schnittstelle zu GitHub für Sie verwalten lassen. Blue Ocean hat das GitHub-Plugin bereits installiert. Dies sind die Schritte zur Konfiguration.

Zunächst sollten Sie Git auf Ihrem System installieren. Das GitHub-Plugin benötigt es nicht unbedingt, aber wenn Sie anfangen, mit Jenkins-Jobs zu arbeiten, müssen Sie es haben. Geben Sie diesen Befehl aus, um Git unter CentOS Linux zu installieren:

Persönliches Zugriffstoken in GitHub

Melden Sie sich bei GitHub an, klicken Sie oben rechts auf Ihr Profilbild, wählen Sie Einstellungen und gehen Sie zu Entwicklereinstellungen . Wählen Sie dann Persönliche Zugriffstoken aus dem linken Seitenleistenmenü oder klicken Sie auf diesen Link, der Sie direkt dorthin führt.

Hier müssen Sie auf Neues Token generieren klicken , wie im Bild unten gezeigt. GitHub wird Sie erneut nach Ihrem Passwort fragen. Was Sie jetzt tun, besteht im Wesentlichen darin, ein neues, anwendungsspezifisches Passwort zu erstellen. Das ist besser als die Weitergabe Ihres tatsächlichen Passworts, da Sie es widerrufen und die dem Token gewährten Berechtigungen einschränken können. Das werden wir auf der Seite tun, die sich öffnet.

Nachdem Sie Ihr Passwort eingegeben haben, müssen Sie dem Token einen Namen geben. Der Name ist nur für dich. Es kann alles sein, zum Beispiel „Jenkins“. Anschließend müssen Sie mindestens den admin:org_hook aktivieren , admin:repo_hook und repo Berechtigungen, wie im Bild unten gezeigt. Sie können alle anderen Kontrollkästchen deaktiviert lassen.

Klicken Sie abschließend auf Token generieren , der Zugangscode erscheint. Sie müssen es kopieren, bevor Sie diese Seite verlassen, da es nicht möglich ist, es erneut anzuzeigen. Wenn Sie es vergessen, löschen Sie das Token und erstellen Sie es neu.

Eingabe der GitHub-Anmeldeinformationen in Jenkins

Wenn Sie das Token kopiert haben, gehen Sie zu Jenkins und wählen Sie Manage Jenkins->Configure System und suchen Sie den Abschnitt mit dem Namen GitHub , wie im Bild unten gezeigt. Wählen Sie im Dropdown-Menü die Option GitHub Server->GitHub Server hinzufügen .

Aktivieren Sie im neuen Abschnitt „GitHub-Server“, der angezeigt wird, das Kontrollkästchen mit der Bezeichnung Hooks verwalten . Wenn Sie dies tun, installiert Jenkins Webhooks auf GitHub für Repos, die Sie überwachen. Wir werden später sehen, dass dies besonders nützlich ist, da wir sie verwenden werden, um eine Simulation oder einen Build in Jenkins auszulösen, wenn ein Benutzer Code an das zugehörige GitHub-Repository überträgt.

Wählen Sie Anmeldeinformationen (Hinzufügen) ->Jenkins nachdem Sie das Kontrollkästchen aktiviert haben, wie im Bild unten gezeigt.

Ändern Sie im sich öffnenden Fenster die Art Dropdown-Liste zu Geheimer Text . Fügen Sie dann das persönliche Zugriffstoken, das Sie zuvor in GitHub generiert haben, in das Secret ein Feld. Schreiben Sie „GitHub“ in das ID-Feld und klicken Sie auf Hinzufügen .

Wenn Sie schließlich wieder im Hauptkonfigurationsmenü sind und den geheimen Text hinzugefügt haben, wählen Sie den neuen GitHub aus Schlüssel aus den Anmeldeinformationen Menü. Drücken Sie dann Verbindung testen um zu überprüfen, ob Jenkins mithilfe des Zugriffstokens mit GitHub kommunizieren kann. Wenn alles gut gelaufen ist, sollten Sie eine Meldung wie im Bild unten sehen.

Scrollen Sie unbedingt zum Ende der Seite und klicken Sie auf Speichern bevor Sie die Konfigurationsseite verlassen.

Wenn Sie auf Probleme stoßen und am Ende mehrere Anmeldeinformationen hinzufügen, können Sie diese löschen, indem Sie zu „Verwalten Jenkins->Benutzer verwalten“ gehen und klicken Sie auf Ihren Benutzernamen. Jetzt gibt es in der linken Seitenleiste einen Menüpunkt namens Anmeldeinformationen . Von dort aus können Sie alle Schlüssel anzeigen und bearbeiten, die Jenkins gespeichert hat.

E-Mail von Jenkins senden

Wir werden Jenkins so konfigurieren, dass es automatisch E-Mails sendet, wenn etwas in Ihrem Code kaputt geht. Um dies zu erreichen, müssen wir einige Änderungen im Manage Jenkins->Configure System vornehmen Menü.

Als Erstes sollten Sie die Absenderadresse eingeben, die Jenkins beim Versenden automatisierter E-Mails verwenden wird. Suchen Sie die Systemadministrator-E-Mail-Adresse Feld auf der Konfigurationsseite und geben Sie die Adresse ein, von der Jenkins senden soll.

Nur eine kurze Anmerkung:Geben Sie am besten eine Adresse ein, die mit dem Jenkins-Domainnamen endet. Dadurch wird die Wahrscheinlichkeit minimiert, dass die E-Mail im Spam-Ordner landet. Der Jenkins-Server ist nicht berechtigt, E-Mails im Namen anderer Domänen zu senden, aber die meisten E-Mail-Dienste akzeptieren Absenderadressen mit derselben Domäne wie der sendende Server. Lesen Sie mehr darüber in diesem Wikipedia-Artikel. Im Bild unten habe ich eine Absenderadresse eingegeben, die mit derselben Domäne wie der Jenkins-Server endet.

Als nächstes müssen wir Jenkins eine Möglichkeit geben, E-Mails zu senden. Der einfachste Weg, dies zu tun, besteht darin, einen SMTP-(Mail-)Server auf dem VPS zu installieren. Sie können dies tun, indem Sie sich anmelden und die folgenden Befehle eingeben:

yum -y install sendmail
systemctl enable sendmail
systemctl restart sendmail

Nachdem Sie sendmail installiert haben , gehen Sie zurück zur Jenkins-Systemkonfiguration und geben Sie „localhost“ im SMTP-Server ein Feld, wie im Bild unten gezeigt.

An dieser Stelle können Sie auch das Kontrollkästchen aktivieren, um das Senden an nicht registrierte Benutzer zu ermöglichen. Das bedeutet Benutzer, die kein Jenkins-Benutzerkonto haben. Später werden wir Jenkins so konfigurieren, dass es eine E-Mail an jede Person sendet, die fehlerhaften Code an GitHub weiterleitet. Jenkins erhält die E-Mail-Adresse des Täters von GitHub, aber das funktioniert nur, wenn die Person ein passendes Jenkins-Konto hat oder wenn wir dieses Kästchen ankreuzen.

Abschließend können Sie die Konfiguration testen, wie im Bild oben gezeigt. Nachdem Sie auf Konfiguration testen geklickt haben , die Meldung „E-Mail wurde erfolgreich gesendet“ sollte erscheinen und die E-Mail sollte Ihren Posteingang erreichen. Überprüfen Sie Ihren Spam-Ordner, wenn Sie die E-Mail nicht innerhalb von fünf Minuten erhalten.

Xilinx Vivado im Batch-Modus installieren

Ich verwende Xilinx Vivado, um den Code in diesem Beispielprojekt zu simulieren, zu kompilieren und zu implementieren. Das Zielgerät ist der Xilinx Zynq-7000 FPGA auf dem ZebBoard-Entwicklungsboard. In diesem Abschnitt zeige ich Ihnen, wie Sie Vivado mit der kostenlosen WebPACK-Lizenz auf dem VPS installieren.

Der erste Schritt besteht darin, den Xilinx Unified Installer:Linux Self Extracting Web Installer herunterzuladen (siehe Abbildung unten). Sie müssen sich anmelden oder ein neues Xilinx-Konto erstellen, um das Installationsprogramm herunterzuladen.

Wenn der Download abgeschlossen ist, müssen Sie ihn von Ihrem Desktop-Computer auf den Jenkins-Server kopieren. Wenn Sie Zugriff auf eine Linux-Shell auf Ihrem Desktop haben, empfehle ich die Verwendung einer sicheren Dateikopie wie im folgenden Befehl:

Bevor Sie das Installationsprogramm ausführen können, müssen Sie einige Pakete installieren, um die Abhängigkeiten von Vivado zu erfüllen. Führen Sie dazu die folgenden Befehle aus:

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

Führen Sie dann das Xilinx Unified-Installationsprogramm wie folgt aus:

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

Die .bin-Datei entpackt die Installationsdateien in ein neues Verzeichnis mit dem Namen Xil_installer . Wenn Sie stattdessen die unten aufgeführte Fehlermeldung erhalten, liegt das daran, dass Sie tar nicht installiert haben .

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

Das Xilinx Unified-Installationsprogramm kann viele verschiedene Xilinx-Tools auf Ihrem System installieren. Daher müssen wir das xsetup ausführen Datei im Xil_installer Verzeichnis, um anzugeben, an welcher Software wir interessiert sind:

cd Xil_installer/
./xsetup -b ConfigGen

Das xsetup Das Skript fordert Sie auf, welche Tools Sie benötigen. Geben Sie „2“ für Vivado ein und dann „1“ für Vivado HL WebPACK , wie in der Auflistung unten gezeigt.

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

Um die Xilinx WebPACK Edition zu installieren, müssen Sie sich während der Installation bei Ihrem Xilinx-Konto anmelden. Auf einem Desktop-Computer führt Sie die Installations-GUI durch diesen Prozess, aber auf dem Server gibt es keine GUI, daher müssen wir uns mit xsetup authentifizieren Skript. Führen Sie den folgenden Befehl aus, um das Authentifizierungstoken zu generieren:

Ich musste den Befehl ein paar Mal ausführen, bevor er funktionierte. Zunächst stoppte das Skript mit der Fehlermeldung „Internetverbindung validiert, Verbindung zum Internet möglich.“ Nach ein paar Versuchen kam ich jedoch durch und konnte mich anmelden. Das Skript fragt nach Ihrer Benutzer-ID und Ihrem Passwort. Das ist die E-Mail-Adresse und das Passwort, die Sie zum Herunterladen des Installationsprogramms von xilinx.com verwendet haben.

Schließlich können Sie Vivado im Batch-Modus installieren. Beim Aufruf des Setup-Skripts müssen Sie die Installationskonfigurationsdatei angeben, damit xsetup weiß, welche Tools heruntergeladen werden müssen. Die Konfigurationsdatei befindet sich in .Xilinx Ordner im Home-Verzeichnis des Root-Benutzers. Führen Sie den folgenden Befehl aus, um die Installation mithilfe der Konfigurationsdatei zu starten:

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

Der Installationsvorgang wird lange dauern. Die Vivado-Installation benötigt 24 GB Speicherplatz. All das wird jetzt vom relativ langsamen Xilinx-Server heruntergeladen. Bei mir dauerte der Download etwas mehr als zwei Stunden.

Nachdem die Installation abgeschlossen ist, sollten Sie testen, ob Vivado erfolgreich im Batch-Modus startet. Xilinx stellt ein Shell-Skript zur Verfügung, das die Umgebung für Sie einrichtet. 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 as well. 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 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 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 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 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.

Zusammenfassung

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. So erstellen Sie einen getakteten Prozess in VHDL
  2. Eingeschränkte zufällige Überprüfung
  3. Grundlegendes VHDL-Quiz – Teil 4
  4. So zeigen Sie VHDL-Variablen in Modelsim während der Simulation an
  5. So installieren Sie kostenlos einen VHDL-Simulator und -Editor
  6. Automatisieren Sie die FPGA-Entwicklung mit Jenkins, Vivado und GitHub auf einem Linux-VPS
  7. So erstellen Sie einen Ringpuffer-FIFO in VHDL
  8. So verwenden Sie die Port Map-Instanziierung in VHDL
  9. So verwenden Sie Konstanten und generische Karten in VHDL
  10. Grundlegendes VHDL-Quiz – Teil 2