Industriële fabricage
Industrieel internet der dingen | Industriële materialen | Onderhoud en reparatie van apparatuur | Industriële programmering |
home  MfgRobots >> Industriële fabricage >  >> Industrial programming >> VHDL

Automatiseer FPGA-ontwikkeling met Jenkins, Vivado en GitHub op een Linux VPS

* Dit artikel bevat een advertentielink voor UpCloud VPS

Continue levering en continue integratie zijn flexibele softwareontwikkelingsmethoden die de cyclustijd tussen codewijziging en implementatie verkorten. Door automatisering te gebruiken om codewijzigingen te verifiëren en releasebestanden samen te stellen, kunnen teams productiever en efficiënter worden.

Softwarebedrijven beoefenen al heel lang continue ontwikkeling, maar u kunt de methoden net zo goed gebruiken voor uw FPGA-projecten. In deze tutorial leert u hoe u een automatiseringsserver op een Virtual Private Server (VPS) instelt met behulp van Jenkins, Xilinx Vivado en het Git/GitHub source-control management (SCM)-systeem.

Wat is Jenkins?

De Jenkins-automatiseringsserver is een gratis en open-sourceprogramma geschreven in Java. Het draait op Windows of Linux. We zullen Linux gebruiken in deze blogpost omdat dat het meest gebruikte platform is voor headless servers.

Jenkins draait als een daemon-proces in Linux of als een service in Windows. Een ingebouwde webserver die Jenkins start wanneer deze wordt gestart, zorgt voor de gebruikersinterface. De meeste gebruikers zullen met Jenkins communiceren via de webinterface. U kunt nieuwe automatiseringsprojecten toevoegen en bestaande beheren via de web-GUI.

De afbeelding hierboven toont de hoofdpagina van de Jenkins-server die we vandaag gaan instellen. Standaard hebben alleen ingelogde gebruikers toegang tot Jenkins, maar voor dit artikel heb ik openbare toegang tot delen van mijn *demoserver ingeschakeld.

* Update:ik heb de demoserver op 13 mei 2020 offline gehaald

Wat u op de hoofdpagina ziet, is een lijst met vacatures. Deze taken kunnen alle soorten taken bevatten en kunnen handmatig worden geactiveerd via de web-GUI. Of ze kunnen automatisch worden geactiveerd via scripts, webhooks of als gevolg van het voltooien van andere taken. Vandaar de term automatiseringsserver .

In ons voorbeeld komt elke taak overeen met een VHDL-module die in een afzonderlijke GitHub-repository wordt bewaard. We laten Jenkins een simulatie uitvoeren en het project bouwen telkens wanneer een ontwikkelaar code naar een van de bewaakte Git-opslagplaatsen pusht. Als een testbench mislukt of als de build kapot gaat, markeert Jenkins de taak als mislukt in de webinterface en stuurt hij automatisch een e-mail naar de persoon die de foutieve code heeft vastgelegd.

Het voorbeeldproject

Automatiseringsservers zijn vooral handig voor teams die aan grotere projecten werken. Daarom heb ik een voorbeeld-FPGA-project gebouwd dat uit acht Git-repository's bestaat. Het project is de 7-segment displayteller van de Fast-Track-cursus, geport naar het Xilinx ZedBoard.

Links naar de acht repository's op GitHub:

  • pakketten (VHDL-pakketten)
  • bcd_encoder (Module)
  • tegen (Module)
  • cijferselector (Module)
  • output_mux (Module)
  • opnieuw instellen (Module)
  • seg7_encoder (Module)
  • seg7 (Topmodule)

Elke opslagplaats bevat een VHDL-module en de bijbehorende testbench. Een uitzondering vormen de pakketten repo, die slechts drie VHDL-pakketten bevat die constanten en typen definiëren. Bovendien is de seg7 top module bevat een beperkingenbestand dat de kloksnelheid en pintoewijzingen van de fysieke implementatie definieert.

De meeste grootschalige VHDL-projecten gebruiken modules uit meer dan één repository. Bedrijven beschikken doorgaans over een bibliotheek met pakketten en modules die ze in veel ontwerpen hergebruiken. Dat is wat ik emuleer door dit vrij eenvoudige ontwerp in zoveel modules op te splitsen.

In ons voorbeeld zijn alle modules afhankelijk van de pakketrepository, en de bovenste module is ook afhankelijk van alle submodules. Ik heb dit opgelost door ze indien nodig te importeren met behulp van standaard Git Submodules. De grafiek hierboven toont de inhoud en afhankelijkheden van alle repo's in dit project.

De Git-opslagplaatsen bevatten ook verschillende niet-ontwerpbestanden, zoals de Jenkins-configuratie en build-scripts. We zullen erover praten in de komende secties van dit artikel.

Virtuele privéserver (VPS)

Hoewel Jenkins op elke Windows- of Linux-computer kan draaien, zou je het voor alle praktische doeleinden op een speciale server willen draaien. De automatiseringsserver moet altijd actief zijn en toegankelijk voor al uw teamleden. Als je een fysieke server met voldoende capaciteit hebt, is dat geweldig. Maar voor de meesten van ons is een snellere en goedkopere oplossing het gebruik van een virtuele privéserver (VPS).

Een VPS is een virtuele computer die u via internet huurt van een hostingbedrijf. Het ziet eruit als een echte Windows- of Linux-computer waarmee u kunt communiceren en welke software u maar wilt kunt installeren. We gaan een Linux-computer gebruiken, omdat dat het meest logisch is voor onze gebruikssituatie.

De site van VHDLwhiz draait, zoals al twee jaar, op een VPS. Ik heb al de moeite genomen om de snelste en beste VPS-provider te vinden, namelijk UpCloud. Uiteraard gaan we UpCloud gebruiken om de VPS voor onze automatiseringsserver in te richten.

Ontvang de UpCloud-bonus van $ 25

Als u UpCloud wilt proberen, heb ik een verwijzingscode die u een tegoed ter waarde van $ 25 geeft bij het aanmelden.

>> Klik hier om de UpCloud-bonus van $ 25 te ontvangen <<

Of gebruik mijn promotiecode tijdens het afrekenen:NV78V6

Door de code te gebruiken, ontvang je de bonus en steun je tegelijkertijd VHDLwhiz. Mogelijk krijg ik voor elke klant die er gebruik van maakt, een bedrag bijgeschreven op mijn UpCloud-account.

Oké, genoeg met het verkooppraatje. Laten we verder gaan met het instellen van de server.

De UpCloud VPS implementeren

Nadat u bent ingelogd op uw nieuwe UpCloud-account, kunt u het proces voor het maken van een nieuwe VPS-instantie starten door naar Servers → Server implementeren te navigeren .

UpCloud heeft veel datacenters over de hele wereld. Selecteer de dichtstbijzijnde locatie voor het hosten van uw nieuwe server. Vervolgens moet u een plan selecteren voor de hoeveelheid bronnen die u aan uw virtuele machine wilt geven. Jenkins gebruikt niet veel bronnen, maar Xilinx Vivado is een echte RAM-zwijn. Kies daarom minimaal het abonnement met 4 GB RAM, zoals weergegeven in de onderstaande afbeelding.

Ik raad aan om de Memory Recommendations-pagina van Xilinx te bekijken, omdat geheugengebruik nauw verband houdt met de complexiteit van de doel-FPGA. De pagina vermeldt het piekgeheugengebruik voor de Zynq-7000 XC7Z045 FPGA die ik gebruik, namelijk 1,9 GB. Ik ontdekte dat het abonnement van 2 GB te weinig was om het ontwerp te routeren. Vivado crashte en het volgende bericht verscheen in de dmesg loggen:

[807816.678940] Onvoldoende geheugen:uitgeschakeld proces 22605 (vivado) total-vm:2046684kB, anon-rss:782916kB, file-rss:308kB, shmem-rss:0kB

Houd er rekening mee dat u de RAM- en CPU-bronnen van uw server altijd eenvoudig kunt upgraden vanuit uw UpCloud-account. Je krijgt niet automatisch de extra ruimte op de harde schijf die bij de duurdere pakketten hoort, zonder het bestandssysteem van de VPS opnieuw te partitioneren, maar het werkt wel. Ter referentie:ik ben begonnen met het plan met 50 GB opslagruimte, en ik heb 61% daarvan gebruikt nadat ik de volledige automatiseringsserver had voltooid. Vivado alleen neemt 24 GB aan ruimte in beslag.

Ik raad u aan de nieuwste CentOS Linux-distributie als besturingssysteem te selecteren, zoals weergegeven in de onderstaande afbeelding. Xilinx Vivado ondersteunt officieel alleen Red Hat Linux, wat niet gratis is. Maar CentOS is een gratis, door de gemeenschap ondersteunde Linux-distributie die Red Hat nauw volgt.

Dan zijn er enkele opties over netwerken die u op de standaardinstellingen kunt laten staan. Er is ook een sectie op de webpagina waar u uw SSH-sleutels kunt uploaden voor wachtwoordloos inloggen. Je kunt deze dingen later altijd configureren met de conventionele Linux-methode voor het uploaden van SSH-sleutels.

Ten slotte moet u de hostnaam en naam van de server opgeven, zoals weergegeven in de onderstaande afbeelding. De hostnaam is het publieke domein dat gebruikers in de browser invoeren om toegang te krijgen tot de Jenkins-server. Als u geen domein of subdomein bij de hand heeft, kunt u altijd toegang krijgen tot de server via het IP-adres ervan. Als u tevreden bent met de instellingen, drukt u op Implementeren knop om de server aan te maken.

Nadat u de server heeft aangemaakt, wordt het automatisch gegenereerde wachtwoord als melding weergegeven. Je kunt dit later wijzigen met behulp van de Linux passwd opdracht. Als u uw SSH-sleutel heeft opgegeven voordat u de server implementeerde, heeft u het wachtwoord helemaal niet nodig. Mocht u ooit de toegang tot uw server verliezen, dan kunt u altijd inloggen vanuit uw UpCloud-account door op Open de consoleverbinding te klikken. , zoals weergegeven in de onderstaande afbeelding.

DNS-zone-instellingen

De nieuwe server krijgt permanente IPv4- en IPv6-adressen toegewezen, te vinden in uw UpCloud-account op Servers->Netwerk . U krijgt toegang tot de server door te SSHen naar de root-account van het openbare IPv4-adres.

Als u het voorbeeld-IP-adres uit de onderstaande afbeelding gebruikt, is het juiste commando dat u op uw Linux-thuiscomputer moet invoeren:

Het is prima om alleen het IP-adres te gebruiken als je dit alleen als experiment doet. Maar een meer praktische oplossing is om een ​​permanente domeinnaam aan de server toe te wijzen. Om dat te doen, moet u een domein aanschaffen bij een van de vele registrars die online beschikbaar zijn.

Omdat ik al eigenaar ben van het domein vhdlwhiz.com, heb ik besloten een subdomein voor de Jenkins-server te maken met de naam jenkins.vhdlwhiz.com . We hebben de domeinnaam correct ingesteld op de UpCloud-server toen we deze implementeerden. Het volgende dat we moeten doen is het subdomein naar het openbare IPv4-adres verwijzen.

De onderstaande afbeelding toont de instellingen die ik invoer in het DNS-zonebestand van mijn domeinnaamregistrar. Als ik wilde dat de server zich op het bovenste domein bevond (vhdlwhiz.com), zou ik het hostnaamveld leeg hebben gelaten. Maar ik wil dat het op het “jenkins”-subdomein van vhdlwhiz.com staat. Daarom voer ik de naam van het subdomein in.

Nadat u de DNS-instellingen heeft gewijzigd, duurt het enige tijd voordat u de domeinnaam kunt gebruiken om toegang te krijgen tot uw website. Normaal gesproken duurt het niet meer dan 20 minuten, maar in extreme gevallen kan het tot 48 uur duren voordat de wijzigingen zich naar alle uithoeken van het internet verspreiden.

Wanneer de wijzigingen van kracht zijn, kunt u bij het inloggen op de server via SSH de domeinnaam gebruiken in plaats van het IP-adres:

ssh root@yoursub.yourdomain.com

Jenkins installeren

Het eerste dat u moet doen nadat u zich heeft aangemeld bij het root-account op uw nieuwe Linux-server, is het bijwerken van alle geïnstalleerde pakketten. In CentOS Linux, yum is de standaard pakketbeheerder. We gaan de yum gebruiken opdracht voor het installeren van de meeste software.

Geef de volgende opdracht om alle geïnstalleerde pakketten bij te werken naar de nieuwste versies:

Nu we weten dat ons systeem up-to-date is, kunnen we doorgaan met de installatie. Maar voordat je de yum uitgeeft opdracht om Jenkins te installeren, gaan we Java-versie 11 expliciet installeren. Dat gaat ons later wat problemen besparen als we Xilinx Vivado installeren.

Momenteel is er geen Java-interpreter aanwezig op onze server, en als we yum vertellen om Jenkins te installeren, zal het Java-versie 8 installeren. Dat werkt goed voor Jenkins, maar het zal later voor problemen voor ons zorgen omdat Vivado afhankelijk is van Java-versie 11.

Installeer Java 11 met behulp van deze opdracht voordat u Jenkins installeert:

yum -y install java-11-openjdk-devel

Jenkins is niet beschikbaar in de standaardsoftwarerepository die bij CentOS wordt geleverd. Gelukkig kunnen we de Jenkins-repository van Red Hat importeren met behulp van de volgende opdrachten:

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

Eindelijk kunnen we doorgaan en Jenkins installeren:

De Jenkins-server start automatisch na de volgende keer opstarten, maar u kunt de server als volgt starten zonder opnieuw op te starten:

U kunt de status van de Jenkins-server altijd controleren door systemctl te gebruiken commando:

Het zal de status van de server samen met eventuele foutmeldingen afdrukken:

Jenkins over onveilige HTTP

Op dit moment draait Jenkins op poort 8080 op de VPS, maar je kunt er geen verbinding mee maken via je webbrowser. Dat komt omdat de CentOS-firewall poort 8080 en poort 80 (HTTP) standaard blokkeert. Wat we kunnen doen om dit op te lossen is door poort 80 in de firewall te openen en deze om te leiden naar poort 8080 met behulp van iptables .

Maar voordat u dat doet, moet u beslissen of u uw site met HTTPS wilt beveiligen. Het probleem met het gebruik van alleen HTTP en poort 80 is dat uw website onveilig wordt. Als u toegang gebruikt via openbare Wi-Fi, kan een kwaadwillende persoon die op dezelfde Wi-Fi zit met een laptop en direct verkrijgbare hacksoftware uw verbinding afluisteren en uw inloggegevens voor Jenkins stelen.

Als je het veiligheidsrisico van niet-versleutelde HTTP wilt vermijden, ga dan naar het volgende gedeelte over het instellen van HTTPS voor Jenkins. Lees anders verder.

Het inschakelen van onveilige HTTP-toegang tot Jenkins is net zo eenvoudig als het geven van de volgende opdrachten:

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

Vervolgens kunt u uw domeinnaam invoeren in uw favoriete browser en de Jenkins Aan de slag pagina zou moeten verschijnen. In Google Chrome wordt in ieder geval de waarschuwing 'Niet veilig' weergegeven in de adresbalk, zoals weergegeven in de onderstaande afbeelding.

Ga verder naar Jenkins instellen sectie als je daar tevreden mee bent.

Jenkins via beveiligde HTTPS

Het hebben van een onbeveiligde website die toegankelijk is voor het publiek vormt een enorm veiligheidsrisico. Jenkins heeft toegang tot uw broncode, en dat geldt ook voor elke hacker die met succes inbreekt op de server. Gelukkig is het beveiligen van de website slechts een paar kopieer- en plakopdrachten verwijderd.

Jenkins kan HTTPS niet zelfstandig verwerken. Daarom moeten we een generieke webserver installeren om verzoeken die via het beveiligde kanaal binnenkomen om te leiden naar de onveilige Jenkins-server. Ik zal Nginx gebruiken, een van de populairste gratis en open-source webservers van dit moment.

Geef de volgende opdracht om Nginx te installeren en te starten:

yum -y install nginx
systemctl start nginx

Vervolgens moeten we zowel de HTTP- als de HTTPS-poort in de firewall openen. We zullen alleen HTTPS-verzoeken verwerken, maar we moeten de HTTP-poort ook open houden omdat we Nginx zullen configureren om alle onveilige verzoeken om te leiden naar de beveiligde poort.

Met deze opdrachten wordt de firewall geopend voor webverkeer:

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

De volgende stap is het installeren van een certificaat dat webbrowsers kunnen gebruiken om te certificeren dat het uw website is waarmee ze communiceren en niet een bedrieger. We gaan de gratis Let’s Encrypt-certificeringsinstantie gebruiken om onze site te beveiligen. De afzonderlijke stappen zijn ingewikkeld, maar gelukkig biedt certbot een script dat dit automatisch voor ons kan doen.

Download en bereid het script voor met de volgende opdrachten:

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

Voer vervolgens het script uit, dat het certificaat installeert en de nodige wijzigingen aanbrengt in het Nginx-configuratiebestand:

Terwijl het script wordt uitgevoerd, wordt u om informatie gevraagd. Beantwoord alle vragen bevestigend (Ja, Accepteren) totdat u wordt gevraagd te kiezen of u HTTP-verkeer wel of niet wilt omleiden naar HTTPS. De onderstaande lijst toont de vragen en mijn voorgestelde antwoord (2). Door Nginx toe te staan onveilige verzoeken om te leiden, zorg je ervoor dat niemand expliciet http:// kan invoeren jouwsite.com en ga naar de onveilige versie van Jenkins. Nginx zal ze doorsturen naar de beveiligde versie.

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

Ten slotte moet u een cronjob inschakelen om het certificaat periodiek te vernieuwen. Anders verloopt deze en weigeren de browsers uw site te openen.

Voer de volgende oneliner-opdracht uit om de dagelijkse cron-taak toe te voegen:

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

De cron-daemon voert het vernieuwingsscript dagelijks om middernacht uit. U kunt de cronjobs weergeven met crontab -l commando en bewerk ze met crontab -e commando. Als u nu uw website bezoekt, ziet u de Nginx-testpagina en niet Jenkins. We zullen dit binnenkort oplossen, maar zorg ervoor dat de waarschuwing 'Niet veilig' uit de Chrome-adresbalk verdwijnt, zoals de onderstaande afbeelding laat zien.

Om Nginx Jenkins te laten bedienen, moet je enkele wijzigingen aanbrengen in de /etc/nginx/nginx.conf bestand. De eer voor dit codefragment gaat naar Kerren's blog op Medium. Het gebruik van de nano-editor is waarschijnlijk de gemakkelijkste manier om het configuratiebestand te bewerken:

nano /etc/nginx/nginx.conf

Zoek het serverblok met uw domeinnaam en voeg de gemarkeerde regels uit de onderstaande lijst toe aan uw nginx.conf-bestand. Merk op dat de eerste van de drie nieuwe regels boven het serverblok gaat, en de rest in het hoofdlocatieblok.

Nadat u het configuratiebestand hebt bijgewerkt, moet u Nginx opnieuw laden om de wijzigingen door te voeren. Optioneel kunt u het configuratiebestand testen voordat u het opnieuw laadt, met behulp van de opdracht:

Nginx zal OK afdrukken of u vertellen op welke regel in nginx.conf bestand de fout is. Als u tevreden bent met de wijzigingen, kunt u de webserver opnieuw laden door het volgende commando te geven:

Wanneer u nu de Jenkins-site in uw browser bezoekt, zou u de pagina Aan de slag van Jenkins moeten zien, zoals weergegeven in de onderstaande afbeelding. Deze keer wordt het via een beveiligde verbinding geserveerd en kunnen we Jenkins veilig blijven configureren vanuit de web-GUI-interface.

Jenkins instellen

De eerste keer dat u uw Jenkins-website bezoekt, wordt u gevraagd om een wachtwoord dat u kunt vinden in een bestand op het Linux-bestandssysteem. Terwijl u bent ingelogd via SSH, gebruikt u de onderstaande opdracht om het wachtwoord weer te geven. Kopieer en plak het in de browser om toegang te krijgen tot de web-GUI:

cat /var/lib/jenkins/secrets/initialAdminPassword

Op het volgende scherm vraagt Jenkins of u de voorgestelde plug-ins wilt installeren, of dat u wilt opgeven welke u wilt installeren. Ga gewoon met de Installeer voorgestelde plug-ins optie voor nu. Je kunt later altijd plug-ins toevoegen of verwijderen.

Op de volgende pagina moet u een admin-gebruiker aanmaken. Vul uw gegevens in en creëer een sterk wachtwoord om te gebruiken met uw nieuwe account. Standaard hebben alleen ingelogde gebruikers toegang tot de Jenkins-server. Anonieme gebruikers zien het inlogvenster alleen als ze uw website bezoeken. De enige reden waarom u toegang had tot mijn *demosite jenkins.vhdlwhiz.com is dat ik wijzigingen heb aangebracht aan de server. Ik heb de Matrix Authorization Strategy-plug-in gebruikt om anonieme toegang tot sommige weergaven te verlenen.

* Update:ik heb de demosite op 13 mei 2020 verwijderd

Wanneer Jenkins klaar is met het installeren van plug-ins, ziet u het bericht “Jenkins is klaar!” bericht, zoals weergegeven in de afbeelding hierboven. Klik op de knop die u naar de lege overzichtspagina van uw nieuwe Jenkins-installatie brengt.

Jenkins-plug-ins installeren

Het eerste dat u hoeft te doen, is een aantal plug-ins installeren. Jenkins heeft een ingebouwde plug-inbeheerder die u kunt gebruiken voor het installeren, bijwerken en verwijderen van extensies. U zult plug-ins vinden die aan de meeste van uw behoeften kunnen voldoen. Gebruik gewoon de zoekfunctie in de plug-inbeheerder als u functionaliteit aan Jenkins wilt toevoegen.

Laten we verder gaan met het installeren van de plug-ins die ik heb gebruikt bij het opzetten van de voorbeeld-Jenkins-server. Kies in de zijbalk Jenkins beheren->Plug-ins beheren->Beschikbaar . Houd er rekening mee dat er geen plug-ins worden vermeld, tenzij u iets in het zoekveld invoert. Zodra u typt, verschijnen ze.

Blauwe Oceaan

De eerste plug-in die ik aanbeveel om te installeren heet Blue Ocean. Deze plug-in is een modernisering van zowel de Jenkins-workflow als de gebruikersinterface. Het bevat ook een aantal andere nuttige plug-ins, zodat u ze niet afzonderlijk hoeft te installeren. Zoek naar “blue ocean” in de plug-inbeheerder en selecteer deze voor installatie, zoals weergegeven in de onderstaande afbeelding.

Op de voortgangspagina van de installatie die verschijnt nadat u op Installeren klikt, heeft u de mogelijkheid om Jenkins opnieuw opstarten wanneer de installatie is voltooid en er geen taken actief zijn te selecteren . Als u het vakje ernaast aanvinkt, wordt Jenkins opnieuw opgestart nadat de installatie van de plug-in is voltooid. Een andere manier om Jenkins opnieuw op te starten is door via SSH op de server in te loggen en de volgende opdracht uit te voeren:

systemctl restart jenkins

Afgezien van de lange lijst met andere plug-ins die door Blue Ocean zijn geïnstalleerd, is er op het eerste gezicht geen merkbare verandering. Maar er komt een nieuw menu-item in de zijbalk, zoals weergegeven in de onderstaande afbeelding. Als je erop klikt, ga je naar de Blue Ocean GUI, die er heel anders uitziet dan de normale Jenkins-interface. Probeer het!

Groene ballen

De volgende plug-in die ik altijd installeer, is puur voor de esthetiek. De Green Balls-plug-in vereist geen configuratie. Zoek eenvoudigweg naar “groene bal” in de plug-inbeheerder en installeer deze zoals weergegeven in de onderstaande afbeelding.

Standaard gebruikt Jenkins blauwe kleurballen op de overzichtspagina om aan te geven dat de status van een taak succesvol is. De reden heeft er iets mee te maken dat de uitvinder van Jenkins Japans is. Interessant is dat in Japan de kleur blauw uitwisselbaar is met groen als het gaat om het aangeven van een OK-status. Meer daarover in dit artikel, waar u de auteur de reden uit de eerste hand kunt horen uitleggen.

Gebruikers uit de meeste andere delen van de wereld geven waarschijnlijk de voorkeur aan groene statusballen. Dat is eenvoudig te verhelpen met de Green Balls-plug-in, zoals weergegeven in de onderstaande afbeelding.

Landelijke plug-in

De volgende plug-in die ik heb geïnstalleerd heet Locale. Zoek naar 'landinstelling' onder Beschikbaar tabblad in plug-inbeheer. Installeer de plug-in, zoals weergegeven in de onderstaande afbeelding.

Met de plug-in kunt u Jenkins dwingen dezelfde taal in de GUI voor alle gebruikers te gebruiken. Standaard vertaalt Jenkins de gebruikersinterface naar de taal die uw webbrowser gebruikt. Ik ben Noors, maar ik heb liever Jenkins in het Engels. De vertaling was een beetje ontoereikend. Bovendien is het zoveel gemakkelijker om in het Engels naar antwoorden te googlen als je wilt weten hoe je iets in Jenkins moet doen.

Het is natuurlijk geheel aan jou of je deze plug-in wilt. Als u het installeert, moet u naar Jenkins beheren->Systeem configureren navigeren en zoek de sectie met de naam Locale . Vervolgens moet u “en_US” invoeren (of welke taal u ook wilt) en het vakje hieronder aanvinken om deze taal voor alle gebruikers te forceren, zoals weergegeven in de onderstaande afbeelding. Vergeet niet naar de onderkant van de pagina te scrollen en op Opslaan te klikken .

De laatste plug-in die je nodig hebt om mijn installatie te klonen is de Sidebar Link-plug-in. Hiermee kunt u aangepaste links toevoegen aan de Jenkins-zijbalk. We zullen het later gebruiken om een ​​link naar de FPGA-releases (bitbestanden) toe te voegen. Zoek naar “zijbalk” in de plug-inbeheerder en installeer de plug-in, zoals weergegeven in de onderstaande afbeelding.

Jenkins verbinden met GitHub

Ongeacht of uw repository openbaar of privé is, u moet Jenkins bepaalde machtigingen geven voor uw GitHub-account. Als je het tenminste op de gemakkelijkst mogelijke manier wilt doen, moet je de Jenkins GitHub-plug-in de interface met GitHub voor je laten beheren. Blue Ocean heeft de GitHub-plug-in al geïnstalleerd. Dit zijn de stappen om het te configureren.

Eerst moet u Git op uw systeem installeren. De GitHub-plug-in heeft het niet strikt nodig, maar als je met Jenkins-taken gaat werken, moet je het hebben. Geef deze opdracht om Git in CentOS Linux te installeren:

Persoonlijk toegangstoken in GitHub

Meld u aan bij GitHub, klik op uw profielfoto in de rechterbovenhoek, kies instellingen en ga naar Ontwikkelaarsinstellingen . Kies vervolgens Persoonlijke toegangstokens in het linkerzijbalkmenu, of klik op deze link die u daar rechtstreeks naartoe brengt.

Hier moet u op Nieuwe token genereren klikken , zoals weergegeven in de onderstaande afbeelding. GitHub zal u nogmaals om uw wachtwoord vragen. Wat u nu doet, is in wezen een nieuw, toepassingsspecifiek wachtwoord maken. Dat is beter dan het delen van uw daadwerkelijke wachtwoord, omdat u het kunt intrekken en de machtigingen die aan het token worden verleend, kunt beperken. Dat is wat we zullen doen op de pagina die wordt geopend.

Wanneer u uw wachtwoord heeft ingevoerd, moet u het token een naam geven. De naam is alleen voor jou. Het kan van alles zijn, 'Jenkins' bijvoorbeeld. Vervolgens moet u minimaal de admin:org_hook inschakelen , admin:repo_hook , en repository machtigingen, zoals weergegeven in de onderstaande afbeelding. U kunt alle andere vakjes uitgeschakeld laten.

Als u ten slotte op Token genereren klikt , de toegangscode verschijnt. U moet het kopiëren voordat u die pagina verlaat, omdat u het niet meer kunt zien. Als u het vergeet, verwijdert u het token en maakt u het opnieuw aan.

De GitHub-inloggegevens invoeren in Jenkins

Wanneer u het token heeft gekopieerd, gaat u naar Jenkins en selecteert u Jenkins beheren->Systeem configureren en zoek de sectie met de naam GitHub , zoals weergegeven in de onderstaande afbeelding. Selecteer in het vervolgkeuzemenu GitHub Server->GitHub Server toevoegen .

Vink in de nieuwe GitHub Server-sectie die verschijnt het vakje aan met het label Hooks beheren . Wanneer je dit doet, installeert Jenkins webhooks op GitHub voor repo's die je monitort. We zullen later zien dat dit bijzonder nuttig is omdat we ze zullen gebruiken om een simulatie te activeren of Jenkins in te bouwen wanneer een gebruiker code naar de bijbehorende GitHub-repository pusht.

Selecteer Inloggegevens (toevoegen)->Jenkins nadat u het vakje heeft aangevinkt, zoals weergegeven in de onderstaande afbeelding.

Wijzig in het geopende venster de Soort vervolgkeuzelijst naar Geheime tekst . Plak vervolgens het persoonlijke toegangstoken dat u eerder in GitHub heeft gegenereerd in het Geheim veld. Schrijf “GitHub” in het ID-veld en druk op Toevoegen .

Wanneer u ten slotte terug bent in het hoofdconfiguratiemenu, selecteert u na het toevoegen van de geheime tekst de nieuwe GitHub sleutel uit de Inloggegevens menukaart. Druk vervolgens op Verbinding testen om te verifiëren dat Jenkins met GitHub kan praten met behulp van het toegangstoken. Als alles goed is gegaan, zou je een bericht moeten zien zoals weergegeven in de onderstaande afbeelding.

Zorg ervoor dat u naar de onderkant van de pagina scrolt en op Opslaan klikt voordat u de configuratiepagina verlaat.

Als u problemen ondervindt en uiteindelijk meerdere inloggegevens moet toevoegen, kunt u deze verwijderen door naar Jenkins->Gebruikers beheren te gaan. en klik op uw gebruikersnaam. Nu zal er in de linkerzijbalk een menu-item zijn met de naam Inloggegevens . Van daaruit kunt u alle sleutels bekijken en bewerken die Jenkins heeft opgeslagen.

E-mail verzenden van Jenkins

We gaan Jenkins configureren om geautomatiseerde e-mails te verzenden wanneer er iets in uw code kapot gaat. Om dat mogelijk te maken, moeten we enkele wijzigingen aanbrengen in Jenkins beheren->Systeem configureren menu.

Het eerste dat u moet doen, is het van-adres invoeren dat Jenkins zal gebruiken bij het verzenden van geautomatiseerde e-mails. Zoek het e-mailadres van de systeembeheerder veld op de configuratiepagina en voer het adres in waarvandaan u wilt dat Jenkins verzendt.

Even een korte opmerking:u kunt het beste een adres invoeren dat eindigt op de Jenkins-domeinnaam. Zo verklein je de kans dat de e-mail in de spamfolder belandt. De Jenkins-server heeft geen toestemming om e-mails te verzenden namens andere domeinen, maar de meeste e-mailservices accepteren afzenderadressen met hetzelfde domein als de verzendende server. Lees daar meer over in dit Wikipedia-artikel. In de onderstaande afbeelding heb ik een van-adres ingevoerd dat eindigt met hetzelfde domein als de Jenkins-server.

Vervolgens moeten we Jenkins een manier geven om e-mails te verzenden. De meest eenvoudige manier om dat te doen is door een SMTP (mail)server op de VPS te installeren. Dat kunt u doen door in te loggen en de volgende opdrachten te geven:

yum -y install sendmail
systemctl enable sendmail
systemctl restart sendmail

Nadat u sendmail heeft geïnstalleerd , ga terug naar de Jenkins-systeemconfiguratie en voer “localhost” in de SMTP-server in veld, zoals weergegeven in de onderstaande afbeelding.

Op dit punt kunt u ook het vakje aanvinken om verzending naar niet-geregistreerde gebruikers toe te staan. Dat betekent gebruikers die geen Jenkins-gebruikersaccount hebben. Later zullen we Jenkins configureren om een ​​e-mail te sturen naar iedereen die foutieve code naar GitHub pusht. Jenkins krijgt het e-mailadres van de dader van GitHub, maar dat werkt alleen als de persoon een overeenkomend Jenkins-account heeft, of als we dit vakje aanvinken.

Ten slotte kunt u de configuratie testen, zoals weergegeven in de afbeelding hierboven. Nadat u op Testconfiguratie heeft gedrukt , het bericht 'E-mail is succesvol verzonden' zou moeten verschijnen en de e-mail zou uw inbox moeten bereiken. Controleer uw spammap als u de e-mail niet binnen vijf minuten ontvangt.

Xilinx Vivado installeren in batchmodus

Ik gebruik Xilinx Vivado om de code in dit voorbeeldproject te simuleren, compileren en implementeren. Het doelapparaat is de Xilinx Zynq-7000 FPGA op het ZebBoard-ontwikkelbord. In deze sectie laat ik je zien hoe je Vivado op de VPS installeert met behulp van de gratis WebPACK-licentie.

De eerste stap is het downloaden van de Xilinx Unified Installer:Linux Self Extracting Web Installer, weergegeven in de onderstaande afbeelding. U moet inloggen of een nieuw Xilinx-account aanmaken om het installatieprogramma te downloaden.

Wanneer de download is voltooid, moet u deze van uw desktopcomputer naar de Jenkins-server kopiëren. Als je toegang hebt tot een Linux-shell op je bureaublad, raad ik je aan een beveiligde bestandskopie te gebruiken, zoals in de volgende opdracht:

Voordat u het installatieprogramma kunt uitvoeren, moet u een paar pakketten installeren om aan de afhankelijkheden van Vivado te voldoen. Voer hiervoor de volgende opdrachten uit:

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

Voer vervolgens het Xilinx Unified-installatieprogramma als volgt uit:

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

Het .bin-bestand zal de installatiebestanden uitpakken naar een nieuwe map met de naam Xil_installer . Als je in plaats daarvan de onderstaande foutmelding krijgt, komt dat omdat je tar niet hebt geïnstalleerd .

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

Het Xilinx Unified-installatieprogramma kan veel verschillende Xilinx-tools op uw systeem installeren. Daarom moeten we xsetup uitvoeren bestand in de Xil_installer directory om aan te geven in welke software we geïnteresseerd zijn:

cd Xil_installer/
./xsetup -b ConfigGen

De xsetup script vraagt u welke tools u wilt hebben. Voer “2” in voor Vivado en vervolgens “1” voor Vivado HL WebPACK , zoals weergegeven in de onderstaande lijst.

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

Om de Xilinx WebPACK-editie te installeren, moet u tijdens de installatie inloggen op uw Xilinx-account. Op een desktopcomputer begeleidt de GUI van het installatieprogramma u door dit proces, maar op de server is er geen GUI, dus we moeten authenticeren met behulp van de xsetup schrift. Voer de volgende opdracht uit om het authenticatietoken te genereren:

Ik moest het commando een paar keer uitvoeren voordat het werkte. In eerste instantie stopte het script met de foutmelding 'Internetverbinding gevalideerd, kan verbinding maken met internet'. Na een paar pogingen kwam ik er echter doorheen en kon ik inloggen. Het script zal om uw gebruikers-ID en wachtwoord vragen. Dat zijn het e-mailadres en wachtwoord dat u hebt gebruikt voor het downloaden van het installatieprogramma van xilinx.com.

Eindelijk bent u klaar om Vivado in batchmodus te installeren. Wanneer u het setup-script aanroept, moet u het installatieconfiguratiebestand zo specificeren dat xsetup weet welke tools te downloaden. Het configuratiebestand bevindt zich in de .Xilinx map in de homedirectory van de rootgebruiker. Voer de volgende opdracht uit om de installatie te starten met behulp van het configuratiebestand:

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

Het installatieproces zal lang duren. De Vivado-installatie gebruikt 24 GB aan ruimte. Dat alles wordt nu gedownload van de relatief trage Xilinx-server. Bij mij duurde het downloaden iets meer dan twee uur.

Nadat de installatie is voltooid, moet u testen of Vivado succesvol opstart in batchmodus. Xilinx biedt een shellscript dat de omgeving voor u inricht. Voordat u Vivado kunt uitvoeren, moet u de bron gebruiken 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 sectie. 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 sectie. 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 bestand. 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 sectie. 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.

Samenvatting

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. Hoe maak je een AXI FIFO in blok RAM met behulp van de ready/valid handshake?
  2. Een For-Loop gebruiken in VHDL
  3. Ondertekend en niet-ondertekend gebruiken in VHDL
  4. VHDL dubbele 7-segment displaycontroller voor Pmod SSD – eenvoudige FPGA-integratie
  5. Een Case-When-statement gebruiken in VHDL
  6. Hoe de tijd in VHDL te vertragen:Wacht op
  7. Een procedure gebruiken in een proces in VHDL
  8. Wachten en wachten tot gebruiken in VHDL
  9. Procedureverklaring - VHDL-voorbeeld
  10. Beginnersgids voor het gebruik van Modelsim voor FPGA- en ASIC-simulatie
  11. Een gekoppelde lijst maken in VHDL