FPGA-ontwikkeling automatiseren met Jenkins, Vivado en GitHub op een Linux VPS
* Dit artikel bevat een advertentielink voor UpCloud VPS
Continuous delivery en continuous integration zijn agile softwareontwikkelmethoden die de cyclusduur tussen codewijziging en implementatie verkorten. Door automatisering te gebruiken om codewijzigingen te verifiëren en releasebestanden te bouwen, kunnen teams productiever en efficiënter worden.
Softwarebedrijven oefenen continuous development al lang, maar u kunt de methoden net zo goed gebruiken voor uw FPGA-projecten. Deze tutorial leert u hoe u een automatiseringsserver opzet op een Virtual Private Server (VPS) met Jenkins, Xilinx Vivado en het Git / GitHub source-control management (SCM) systeem.
Wat is Jenkins?
De Jenkins-automatiseringsserver is een gratis en open-source programma geschreven in Java. Het draait op Windows of Linux. We zullen Linux in deze blogpost gebruiken omdat dat het meest voorkomende platform is voor headless servers.
Jenkins draait als een daemon-proces in Linux of als een service in Windows. Een ingebouwde webserver die Jenkins lanceert bij het starten biedt de gebruikersinterface. Meeste gebruikers zullen interactie hebben met Jenkins 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 zullen opzetten. Standaard hebben alleen ingelogde gebruikers toegang tot Jenkins, maar voor dit artikel heb ik publieke toegang tot delen van mijn *demo-server ingeschakeld.
* Update: Ik haalde de demo-server af op 13 mei 2020
Wat u ziet op de hoofdpagina is een lijst met jobs. Deze jobs kunnen elke taak bevatten en handmatig getriggerd worden via de web GUI. Of ze kunnen automatisch getriggerd worden via scripts, webhooks, of als resultaat van andere jobs die voltooien. Daher de term automatiseringsserver.
In ons voorbeeld correspondeert elke job met een VHDL-module die in een aparte GitHub-repository wordt bewaard. We laten Jenkins een simulatie draaien en het project bouwen wanneer een ontwikkelaar code pusht naar een van de gemonitorde Git-repo's. Als een testbench faalt of de build breekt, markeert Jenkins de job als mislukt in de webinterface en stuurt automatisch een e-mail naar de persoon die de foutieve code committe.
Het voorbeeldproject
Automatiseringsservers zijn het nuttigst voor teams die aan grotere projecten werken. Daarom heb ik een voorbeeld FPGA-project samengesteld dat uit acht Git-repositories bestaat. Het project is de 7-segment display teller uit de Fast-Track cursus, geport naar de Xilinx ZedBoard.
Links naar de acht repo's op GitHub:
- packages (VHDL packages)
- bcd_encoder (Module)
- counter (Module)
- digit_selector (Module)
- output_mux (Module)
- reset (Module)
- seg7_encoder (Module)
- seg7 (Top module)
Elke repo bevat een VHDL-module en de bijbehorende testbench. Een uitzondering is de packages repo, die alleen drie VHDL-packages bevat die constanten en types definiëren. Daarnaast bevat de seg7 top module een constraints-bestand dat de kloksnelheid en pin-toewijzingen van de fysieke implementatie definieert.
Meeste grootschalige VHDL-projecten gebruiken modules uit meer dan één repository. Bedrijven hebben typisch een bibliotheek van packages en modules die ze hergebruiken in veel ontwerpen. Dat emuleer ik door dit redelijk simpele ontwerp in zoveel modules te splitsen.
In ons voorbeeld zijn alle modules afhankelijk van de packages repo, en de top module is afhankelijk van alle submodules ook. Ik heb dit opgelost door ze te importeren zoals nodig met behulp van standaard Git Submodules. De grafiek hierboven toont de inhoud en afhankelijkheden van alle repo's in dit project.
De Git-repositories bevatten ook verschillende niet-ontwerpbestanden, zoals de Jenkins-configuratie en buildscripts. We zullen erover praten in de komende secties van dit artikel.
Virtual private server (VPS)
Hoewel Jenkins op elke Windows- of Linux-computer kan draaien, voor alle praktische doeleinden wilt u het op een toegewijde server draaien. De automatiseringsserver moet altijd draaien en bereikbaar zijn voor al uw teamleden. Als u een fysieke server met voldoende capaciteit liggen heeft, is dat geweldig. Maar voor de meeste van ons is een snellere en goedkopere oplossing het gebruik van een virtual private server (VPS).
Een VPS is een virtuele computer die u huurt van een hostingbedrijf via het internet. Het verschijnt als een echte Windows- of Linux-computer waarmee u kunt interacteren en waar u elke software kunt installeren. We gaan een Linux-computer gebruiken omdat dat het meest zinvol is voor ons gebruiksscenario.
De VHDLwhiz-site draait op een VPS, al twee jaar lang. Ik heb al de moeite gedaan om de snelste en beste VPS-provider te vinden, wat UpCloud is. Natuurlijk gaan we UpCloud gebruiken om de VPS voor onze automatiseringsserver op te zetten.
Krijg de $25 UpCloud bonus
Als u UpCloud wilt uitproberen, heb ik een verwijzingscode die u $25 aan tegoed geeft bij aanmelding.
>> Klik hier voor de $25 UpCloud bonus <<
Of gebruik mijn promotiecode bij afrekenen: NV78V6
Door de code te gebruiken, krijgt u de bonus en steunt u VHDLwhiz tegelijkertijd. Ik krijg misschien enige fondsen gecrediteerd op mijn UpCloud-account voor elke klant die het gebruikt.
Genug met de salestalk. Laten we doorgaan met het opzetten van de server.
De UpCloud VPS implementeren
Nadat u bent ingelogd in uw nieuwe UpCloud-account, kunt u het proces starten om een nieuwe VPS-instantie te maken door te navigeren naar Servers → Deploy server.
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 hoeveel bronnen u aan uw virtuele machine wilt geven. Jenkins gebruikt niet veel bronnen, maar Xilinx Vivado is een echte RAM-hongerder. Daarom moet u ten minste het plan met 4 GB RAM kiezen, zoals in de afbeelding hieronder getoond.
Ik raad aan om eens te kijken naar Xilinx' Memory Recommendations pagina omdat geheugengebruik nauw verbonden is met de complexiteit van de doel-FPGA. De pagina lijst het piekgeheugengebruik voor de Zynq-7000 XC7Z045 FPGA die ik gebruik op 1,9 GB. Ik ontdekte dat het 2 GB plan te weinig was voor het routeren van het ontwerp. Vivado crashede, en het volgende bericht verscheen in de dmesg log:
[807816.678940] Out of memory: Killed process 22605 (vivado) total-vm:2046684kB, anon-rss:782916kB, file-rss:308kB, shmem-rss:0kB
Let op dat u de RAM en CPU-bronnen van uw server altijd eenvoudig kunt upgraden vanuit uw UpCloud-account. U krijgt niet automatisch de extra harde schijfruimte die bij de duurdere pakketten hoort zonder het bestandssysteem van de VPS te herpartitioneren, maar het zal draaien. Voor referentie, ik begon met het plan van 50 GB opslag, en ik heb 61% daarvan gebruikt na het voltooien van de hele automatiseringsserver. Vivado alleen neemt 24 GB ruimte in beslag.
Ik raad aan dat u de meest recente CentOS Linux-distributie selecteert als besturingssysteem, zoals in de afbeelding hieronder getoond. Xilinx Vivado ondersteunt officieel alleen Red Hat Linux, wat niet gratis is. Maar CentOS is een gratis, door de community ondersteunde Linux-distributie die Red Hat nauw volgt.
Dan zijn er enkele netwerkopties die u op de standaarden kunt laten. Er is ook een sectie op de webpagina waar u uw SSH-sleutels kunt uploaden voor wachtwoordloze inlog. U kunt deze dingen later altijd configureren met de conventionele Linux-methode voor het uploaden van SSH-sleutels.
Tot slot moet u de hostname en naam van de server specificeren, zoals in de afbeelding hieronder getoond. De hostname is het publieke domein dat gebruikers in de browser zullen invoeren om toegang te krijgen tot de Jenkins-server. Als u geen domein of subdomein gereed heeft, kunt u de server altijd benaderen met zijn IP-adres. Wanneer u tevreden bent met de instellingen, druk op de Deploy knop om de server te creëren.
Nadat u de server heeft aangemaakt, wordt het autogegenereerde wachtwoord als een notificatie getoond. U kunt dit later wijzigen met het Linux passwd commando. Als u uw SSH-sleutel heeft opgegeven voordat u de server implementeerde, hebt u het wachtwoord helemaal niet nodig. Mocht u ooit toegang tot uw server verliezen, kunt u altijd inloggen vanuit uw UpCloud-account door Open the console connection te klikken, zoals in de afbeelding hieronder getoond.
DNS-zone-instellingen
De nieuwe server krijgt permanente IPv4- en IPv6-adressen toegewezen, te vinden in uw UpCloud-account bij Servers->Network. U kunt de server benaderen door te SSH'en in het root-account van het publieke IPv4-adres.
Met behulp van het voorbeeld IP-adres uit de afbeelding hieronder, zou het geschikte commando om in te voeren op uw Linux-thuiscomputer zijn:
Het is OK om alleen het IP-adres te gebruiken als u dit doet als experiment. Maar een praktischere oplossing is om een permanente domeinnaam aan de server toe te wijzen. Daarvoor moet u een domein kopen bij een van de vele registrars die online beschikbaar zijn.
Aangezien ik al het vhdlwhiz.com-domein bezit, besloot ik een subdomein voor de Jenkins-server te maken genaamd jenkins.vhdlwhiz.com. We stelden de domeinnaam correct in op de UpCloud-server toen we deze implementeerden. Het volgende wat we moeten doen is het subdomein wijzen naar het publieke IPv4-adres.
De afbeelding hieronder toont de instellingen die ik invoer in het DNS-zonebestand van mijn domeinnaamregistrar. Als ik de server op het hoofddomein (vhdlwhiz.com) wilde, had ik het hostname-veld leeg gelaten. Maar ik wil het op het "jenkins" subdomein van vhdlwhiz.com. Daarom voer ik de naam van het subdomein in.
Het duurt enige tijd na het wijzigen van de DNS-instellingen voordat u de domeinnaam kunt gebruiken om toegang te krijgen tot uw website. Meestal duurt het niet langer dan 20 minuten, maar in extreme gevallen kan het tot 48 uur duren voordat de wijzigingen naar elk hoekje van het internet zijn doorgedrongen.
Wanneer de wijzigingen van kracht zijn, kunt u de domeinnaam gebruiken in plaats van het IP-adres bij het inloggen op de server via SSH:
ssh root@yoursub.yourdomain.com
Jenkins installeren
Het eerste wat u moet doen na het inloggen in het root-account op uw nieuwe Linux-server is alle geïnstalleerde pakketten bij te werken. In CentOS Linux is yum de standaardpakketbeheerder. We gaan het yum commando gebruiken voor het installeren van de meeste software.
Voer het volgende commando uit om alle geïnstalleerde pakketten naar de nieuwste versies bij te werken:
Nu we weten dat ons systeem up-to-date is, kunnen we doorgaan met de installatie. Maar voordat we het yum commando geven om Jenkins te installeren, gaan we Java versie 11 expliciet installeren. Dat bespaart ons later problemen wanneer we Xilinx Vivado installeren.
Momenteel is er geen Java-interpreter aanwezig op onze server, en als we yum vertellen Jenkins te installeren, gaat het Java versie 8 installeren. Dat werkt goed voor Jenkins, maar zal later problemen voor ons creëren omdat Vivado afhankelijk is van Java versie 11.
Installeer Java 11 met dit commando voordat u Jenkins installeert:
yum -y install java-11-openjdk-devel
Jenkins is niet beschikbaar in de standaardsoftware-repository die bij CentOS hoort. Gelukkig kunnen we de Jenkins-repo van Red Hat importeren met de volgende commando's:
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
Ten slotte kunnen we Jenkins installeren:
De Jenkins-server start automatisch na de volgende herstart, maar u kunt de server starten zonder herstarten als volgt:
U kunt de status van de Jenkins-server altijd controleren met het systemctl commando:
Het zal de status van de server afdrukken samen met eventuele foutmeldingen:
Jenkins over onveilige HTTP
Op dit moment draait Jenkins op poort 8080 op de VPS, maar u hebt geen manier om ermee te verbinden met uw webbrowser. Dat is omdat de CentOS-firewall poort 8080 en poort 80 (HTTP) standaard blokkeert. Wat we kunnen doen om dat op te lossen is poort 80 in de firewall openen en het omleiden naar poort 8080 met iptables.
Maar voordat u dat doet, moet u beslissen of u uw site wilt beveiligen met HTTPS. Het probleem met alleen HTTP en poort 80 is dat uw website onveilig zal zijn. Als u het benadert via publieke Wi-Fi, kan een kwaadwillend persoon op dezelfde Wi-Fi met een laptop en gemakkelijk beschikbare hacksoftware uw verbinding afhoken en uw inloggegevens voor Jenkins stelen.
Als u het beveiligingsrisico van onversleutelde HTTP wilt vermijden, ga dan naar de volgende sectie over het instellen van HTTPS voor Jenkins. Anders, blijf lezen.
Onveilige HTTP-toegang tot Jenkins inschakelen is zo eenvoudig als de volgende commando's uitvoeren:
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
Dan kunt u uw domeinnaam in uw favoriete browser invoeren, en de Jenkins Getting Started pagina zou moeten verschijnen. Tenminste in Google Chrome, de waarschuwing "Niet veilig" wordt weergegeven in de adresbalk, zoals in de afbeelding hieronder getoond.
Ga door naar de Jenkins instellen sectie als u tevreden bent met dat.
Jenkins over veilige HTTPS
Een onbeveiligde website die publiek toegankelijk is, is een enorm beveiligingsrisico. Jenkins kan toegang krijgen tot uw broncode, en elke hacker die met succes inbreekt op de server ook. Gelukkig is het beveiligen van de website slechts een paar copy-paste commando's ver.
Jenkins kan HTTPS niet zelf aan. Daarom moeten we een generieke webserver installeren om verzoeken die via de beveiligde kanaal aankomen, door te sturen naar de onbeveiligde Jenkins-server. Ik zal Nginx gebruiken, een van de meest populaire gratis en open-source webservers vandaag.
Voer het volgende commando uit om Nginx te installeren en te starten:
yum -y install nginx systemctl start nginx
Dan moeten we zowel de HTTP- als HTTPS-poorten in de firewall openen. We zullen alleen HTTPS-verzoeken serveren, maar we moeten de HTTP-poort open houden omdat we Nginx zullen configureren om alle onbeveiligde verzoeken door te sturen naar de beveiligde poort.
Deze commando's openen de firewall 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 een certificaat installeren dat webbrowsers kunnen gebruiken om te certifiëren dat het uw website is waar ze mee interacteren en niet een imposteur. We gaan de gratis Let's Encrypt certificeringsinstantie gebruiken om onze site te beveiligen. De individuele stappen zijn gecompliceerd, maar gelukkig biedt certbot een script dat het automatisch voor ons kan doen.
Download en bereid het script voor met de volgende commando's:
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 benodigde wijzigingen in het Nginx-configuratiebestand aanbrengt:
Terwijl het script draait, zal het u om informatie vragen. Beantwoord bevestigend (Ja, Accepteren) op alle vragen totdat u wordt gevraagd of u HTTP-verkeer wilt doorsturen naar HTTPS. De onderstaande lijst toont de vragen, en mijn voorgestelde antwoord (2). Het toestaan dat Nginx onbeveiligde verzoeken doorstuurt, zorgt ervoor dat niemand expliciet https://yoursite.com kan invoeren en op de onbeveiligde versie van Jenkins komt. 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
Tot slot moet u een cron-job inschakelen om het certificaat periodiek te vernieuwen. Anders verloopt het, en zullen browsers weigeren uw site helemaal te openen.
Voer de volgende one-liner commando uit om de dagelijkse cron-job toe te voegen:
echo "0 0 * * * /snap/bin/certbot renew --quiet" | crontab -
De cron-daemon zal het vernieuwingscript dagelijks om middernacht uitvoeren. U kunt de cron-jobs lijsten met het crontab -l commando en bewerken met het crontab -e commando. Als u nu uw website bezoekt, ziet u de Nginx-testpagina, en niet Jenkins. We zullen dit straks oplossen, maar zorg ervoor dat de waarschuwing "Niet veilig" verdwenen is uit de Chrome-adresbalk, zoals de afbeelding hieronder toont.
Om Nginx Jenkins te laten serveren, moet u enkele wijzigingen aanbrengen in het /etc/nginx/nginx.conf bestand. Credits voor deze code-snippet gaan naar Kerren's blog op Medium. Het gebruik van de nano-editor is waarschijnlijk de makkelijkste manier om het configuratiebestand te bewerken:
nano /etc/nginx/nginx.conf
Zoek het serverblok dat uw domeinnaam noemt en voeg de gemarkeerde regels uit de onderstaande listing toe aan uw nginx.conf bestand. Let op dat de eerste van de drie nieuwe regels boven het serverblok gaat, en de rest in het root location-blok.
Nadat u het configuratiebestand heeft bijgewerkt, moet u Nginx herladen voor de wijzigingen van kracht te laten worden. Optioneel kunt u het configuratiebestand testen voordat u herlaadt met het commando:
Nginx zal OK afdrukken of vertellen op welke regel in het nginx.conf bestand de fout zit. Wanneer u tevreden bent met de wijzigingen, kunt u de webserver herladen door het volgende commando te geven:
Wanneer u nu de Jenkins-site in uw browser bezoekt, zou u de Getting Started pagina van Jenkins moeten zien, zoals in de afbeelding hieronder getoond. Deze keer wordt het geserveerd via een beveiligde verbinding, en we kunnen veilig doorgaan met het configureren van Jenkins vanuit de web GUI-interface.
Jenkins instellen
De eerste keer dat u uw Jenkins-website bezoekt, zal het om een wachtwoord vragen dat in een bestand op het Linux-bestandssysteem staat. Terwijl u ingelogd bent via SSH, gebruikt u het onderstaande commando om het wachtwoord te tonen. Kopieer-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 plugins wilt installeren, of of u wilt specificeren welke te installeren. Gaat gewoon met de Install suggested plugins optie voor nu. U kunt plugins later altijd toevoegen of verwijderen.
Op de volgende pagina moet u een admin-gebruiker aanmaken. Vul uw gegevens in en creeer een sterk wachtwoord voor uw nieuwe account. Standaard hebben alleen ingelogde gebruikers toegang tot de Jenkins-server. Anonieme gebruikers zullen alleen het inlogdialoogvenster zien als ze uw website bezoeken. De enige reden waarom u mijn *demo-site jenkins.vhdlwhiz.com kon benaderen is dat ik wijzigingen aan de server heb aangebracht. Ik gebruikte de Matrix Authorization Strategy plugin om anonieme toegang toe te kennen tot sommige weergaven.
* Update: Ik haalde de demo-site af op 13 mei 2020
Wanneer Jenkins klaar is met het installeren van plugins, ziet u het bericht "Jenkins is ready!", zoals in de afbeelding hierboven getoond. Klik op de knop die u naar de lege overzichtspagina van uw verse Jenkins-installatie brengt.
Jenkins-plugins installeren
Het eerste wat u moet doen is een boel plugins installeren. Jenkins heeft een ingebouwde pluginbeheerder die u kunt gebruiken voor het installeren, bijwerken en verwijderen van extensies. U vindt plugins die de meeste van uw behoeften kunnen verzorgen. Gebruik gewoon de zoekfunctie in de pluginbeheerder wanneer u functionaliteit aan Jenkins wilt toevoegen.
Laten we doorgaan met het installeren van de plugins die ik gebruikte bij het opzetten van de voorbeeld Jenkins-server. Vanuit de zijbalk, kies Manage Jenkins->Manage Plugins->Available. Let op dat geen plugins worden getoond tenzij u iets in het zoekveld intypt. Zodra u typt, verschijnen ze.
Blue Ocean
De eerste plugin die ik aanbeveel te installeren heet Blue Ocean. Deze plugin is een modernisering van de Jenkins-workflow en de gebruikersinterface. Het trekt ook een boel andere nuttige plugins mee, zodat u ze niet hoeft te installeren afzonderlijk. Zoek naar "blue ocean" in de pluginbeheerder en selecteer het voor installatie, zoals in de afbeelding hieronder getoond.
Op de installatievoortgangspagina die verschijnt nadat u op installeren klikt, hebt u de optie om Restart Jenkins when installation is complete and no jobs are running te selecteren. Als u het vakje ernaast aanvinkt, herstart Jenkins na voltooiing van de plugin-installatie. Een andere manier om Jenkins te herstarten is in te loggen op de server via SSH en het volgende commando uit te voeren:
systemctl restart jenkins
Naast de lange lijst met andere plugins die door Blue Ocean werden geïnstalleerd, is er op eerste gezicht geen opvallende verandering. Maar er zal een nieuw menu-item in de zijbalk zijn, zoals in de afbeelding hieronder getoond. Wanneer erop geklikt, brengt het u naar de Blue Ocean GUI, wat er heel anders uitziet dan de normale Jenkins-interface. Probeer het!
Green Balls
De volgende plugin die ik altijd installeer is puur voor esthetiek. De Green Balls plugin vereist geen configuratie. Zoek gewoon naar "green ball" in de pluginbeheerder en installeer het, zoals in de afbeelding hieronder getoond.
Standaard gebruikt Jenkins blauwe kleurballen op de overzichtspagina om aan te duiden dat de status van een job succesvol is. De reden heeft te maken met het feit dat de uitvinder van Jets Japans is. Interessant genoeg, in Japan is de kleur blauw uitwisselbaar met groen wanneer het aankomt op het aanwijzen van een OK-status. Meer daarover in dit artikel, waar u de auteur kunt horen de reden uitleggen uit eerste hand.
Gebruikers uit de meeste andere delen van de wereld zouden waarschijnlijk groene statusballen prefereren. Dat is eenvoudig opgelost door de Green Balls plugin, zoals in de afbeelding hieronder getoond.
Locale plugin
De volgende plugin die ik installeerde heet Locale. Zoek naar "locale" onder het Available tabblad in de pluginbeheerder. Installeer de plugin, zoals in de afbeelding hieronder getoond.
De plugin stelt u in staat Jenkins te dwingen om 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 zou liever Jenkins in het Engels hebben. De vertaling was een beetje ontoereikend. Ook is het zo veel makkelijker om in het Engels te googelen naar antwoorden als u moet uitvinden hoe u iets in Jenkins moet doen.
Natuurlijk is het volledig aan u of u deze plugin wilt. Als u hem installeert, moet u navigeren naar Manage Jenkins->Configure System en de sectie zoeken genaamd Locale. Dan moet u "en_US" (of welke taal u ook wilt) invoeren en het vakje eronder aanvinken om deze taal te forceren op alle gebruikers, zoals in de afbeelding hieronder getoond. Vergeet niet om naar beneden te scrollen en op Save te klikken.
De laatste plugin die u nodig heeft om mijn setup te klonen is de Sidebar Link plugin. Het stelt u in staat om aangepaste links toe te voegen aan de Jenkins-zijbalk. We zullen het later gebruiken om een link toe te voegen aan de FPGA-releases (bitfiles). Zoek naar "sidebar" in de pluginbeheerder en installeer de plugin, zoals in de afbeelding hieronder getoond.
Jenkins verbinden met GitHub
Ongeacht of uw repository publiek of privé is, moet u Jenkins enkele rechten geven op uw GitHub-account. Tenminste als u het op de gemakkelijkste manier wilt doen, moet u de Jenkins GitHub-plugin de interface met GitHub voor u laten beheren. Blue Ocean heeft de GitHub-plugin al geïnstalleerd. Dit zijn de stappen om het te configureren.
Eerst moet u Git op uw systeem installeren. De GitHub-plugin heeft dit niet strikt nodig, maar wanneer u begint met Jenkins-jobs, moet u het hebben. Voer dit commando uit om Git in CentOS Linux te installeren:
Persoonlijke toegangstoken in GitHub
Meld u aan bij GitHub, klik op uw profielfoto in de rechterbovenhoek, kies instellingen, en ga naar Developer Settings. Kies dan Personal access tokens uit het linkermenu, of klik op deze link die u er direct brengt.
Hier moet u op Generate new token klikken, zoals in de afbeelding hieronder getoond. GitHub zal u nogmaals om uw wachtwoord vragen. Wat u nu doet is essentieel een nieuw, toepassingsspecifiek wachtwoord aanmaken. Dat is beter dan uw eigen wachtwoord delen omdat u het kunt intrekken en de machtigingen die aan de token worden verleend kunt beperken. Dat is wat we op de pagina die opent zullen doen.
Nadat u uw wachtwoord heeft ingevoerd, moet u de token een naam geven. De naam is gewoon voor u. Het kan alles zijn, "Jenkins," bijvoorbeeld. Vervolgens moet u ten minste de admin:org_hook, admin:repo_hook, en repo machtigingen inschakelen, zoals in de afbeelding hieronder getoond. U kunt alle andere vakjes ongevinkt laten.
Ten slotte, wanneer u op Generate token klikt, verschijnt de toegangscode. U moet het kopiëren voordat u die pagina verlaat omdat het niet meer mogelijk is om het te zien. Als u het vergeet, verwijder de token en maak het opnieuw aan.
De GitHub-referenties invoeren in Jenkins
Wanneer u de token hebt gekopieerd, ga naar Jenkins, selecteer Manage Jenkins->Configure System, en zoek de sectie genaamd GitHub, zoals in de afbeelding hieronder getoond. Uit het dropdown-menu, selecteer Add GitHub Server->GitHub Server.
In de nieuwe GitHub Server-sectie die verschijnt, vink het vakje aan gelabeld Manage hooks. Wanneer u dit doet, installeert Jenkins webhooks op GitHub voor repo's die u monitoren. We zullen later zien dat dit met name nuttig is omdat we ze zullen gebruiken om een simulatie of build in Jenkins te triggeren wanneer een gebruiker code pusht naar de bijbehorende GitHub-repository.
Selecteer Credentials (Add)->Jenkins nadat u het vakje heeft aangevinkt, zoals in de afbeelding hieronder getoond.
In het venster dat opent, wijzig het Kind dropdown naar Secret text. Plak dan de persoonlijke toegangstoken die u eerder in GitHub gegenereerde in het Secret veld. Schrijf "GitHub" in het ID-veld en druk op Add.
Ten slotte, wanneer u terug bent in het hoofdconfiguratiemenu, na het toevoegen van de geheime tekst, selecteer de nieuwe GitHub sleutel uit het Credentials menu. Druk dan op Test connection om te verifiëren dat Jenkins met GitHub kan praten met behulp van de toegangstoken. Als alles goed ging, zou u een bericht moeten zien zoals in de afbeelding hieronder getoond.
Zorg ervoor dat u naar beneden scrolt en op Save klikt voordat u de configuratiepagina verlaat.
Als u in problemen komt en uiteindelijk meerdere referenties toevoegt, kunt u ze verwijderen door naar Manage Jenkins->Manage Users te gaan, en op uw gebruikersnaam te klikken. Nu, in de linkerbalk, zal er een menu-item genaamd Credentials zijn. Daar kunt u alle sleutels bekijken en bewerken die Jenkins heeft opgeslagen.
E-mail verzenden vanuit Jenkins
We gaan Jenkins configureren om geautomatiseerde e-mails te sturen wanneer er iets breekt in uw code. Om dat te laten gebeuren, moeten we enkele wijzigingen aanbrengen in het Manage Jenkins->Configure System menu.
Het eerste wat u moet doen is het from-adres invoeren dat Jenkins zal gebruiken bij het verzenden van geautomatiseerde e-mails. Zoek het System Admin e-mail address veld op de configuratiepagina, en voer het adres in dat u wilt dat Jenkins gebruikt als afzender.
Even een korte notitie: het is het beste om een adres in te voeren dat eindigt met de Jenkins-domeinnaam. Dat minimaliseert de kans dat de e-mail in de spam-map terechtkomt. De Jenkins-server heeft geen toestemming om e-mails namens andere domeinen te versturen, maar de meeste e-mailservices accepteren from-adressen met hetzelfde domein als de verzendende server. Lees er meer over in dit Wikipedia-artikel. In de afbeelding hieronder heb ik een from-adres ingevoerd dat eindigt met hetzelfde domein als de Jenkins-server.
Vervolgens moeten we Jenkins een manier geven om e-mails te versturen. De meest voor de hand liggende manier is om een SMTP (mail) server op de VPS te installeren. U kunt dat doen door in te loggen en de volgende commando's uit te voeren:
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 het SMTP server veld in, zoals in de afbeelding hieronder getoond.
Op dit moment kunt u ook het vakje aanklikken om verzenden 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 haalt het e-mailadres van de schuldige op uit GitHub, maar dat werkt alleen als de persoon een passend Jenkins-account heeft, of als we dit vakje aanklikken.
Ten slotte kunt u de configuratie testen, zoals in de afbeelding hierboven getoond. Nadat u op Test configuration drukt, zou het bericht "Email was successfully sent" moeten verschijnen, en de e-mail uw inbox moeten bereiken. Controleer uw spam-map als u de e-mail niet binnen vijf minuten ontvangt.
Xilinx Vivado installeren in batch-modus
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 zien hoe u 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, zoals in de afbeelding hieronder getoond. U moet inloggen of een nieuw Xilinx-account aanmaken om de installer te downloaden.
Wanneer de download is voltooid, moet u het van uw desktopcomputer naar de Jenkins-server kopiëren. Als u toegang heeft tot een Linux-shell op uw desktop, stel ik voor beveiligde bestandscopy te gebruiken als in het volgende commando:
Voordat u de installer kunt uitvoeren, moet u een paar pakketten installeren om aan Vivado's afhankelijkheden te voldoen. Voer de volgende commando's uit om dat te doen:
yum -y install tar yum -y install java-11-openjdk-devel yum -y install ncurses-compat-libs yum -y install gcc
Voer dan de Xilinx Unified installer als volgt uit:
./Xilinx_Unified_2019.2_1106_2127_Lin64.bin --keep --noexec --target Xil_installer
Het .bin-bestand pakt de installatiebestanden uit naar een nieuwe map genaamd Xil_installer. Als u de onderstaande fout krijgt, is het omdat u tar niet hebt geïnstalleerd.
Verifying archive integrity... All good. Uncompressing Xilinx InstallerExtraction failed. Terminated
De Xilinx Unified installer kan veel verschillende Xilinx-tools op uw systeem installeren. Daarom moeten we het xsetup bestand in de Xil_installer map uitvoeren om te specificeren welke software we willen:
cd Xil_installer/ ./xsetup -b ConfigGen
Het xsetup script vraagt u welke tools u wilt hebben. Voer "2" in voor Vivado, en dan "1" voor Vivado HL WebPACK, zoals in de onderstaande listing getoond.
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 inloggen op uw Xilinx-account tijdens de installatie. Op een desktopcomputer begeleidt de installer-GUI u door dit proces, maar op de server is er geen GUI, dus moeten we authenticeren met behulp van het xsetup script. Voer het volgende commando uit om het authenticatietoken te genereren:
Ik moest het commando een paar keer uitvoeren voordat het werkte. Eerst stopte het script met de fout "Internet connection validated, can connect to internet." Echter, na een paar pogingen kwam ik erdoor, en kon ik inloggen. Het script zal vragen om uw gebruikers-ID en wachtwoord. Dat is het e-mailadres en wachtwoord die u gebruikte voor het downloaden van de installer van xilinx.com.
Ten slotte bent u klaar om Vivado in batch-modus te installeren. Bij het aanroepen van het setup-script moet u het installatieconfiguratiebestand specificeren, zodat xsetup weet welke tools te downloaden. Het configuratiebestand zit in de .Xilinx map in de home-directory van de root-gebruiker. Voer het volgende commando uit om de installatie te starten met het configuratiebestand:
./xsetup -a XilinxEULA,3rdPartyEULA,WebTalkTerms \ -b Install -c ~/.Xilinx/install_config.txt
Het installatieproces zal lang duren om te voltooien. De Vivado-installatie gebruikt 24 GB ruimte. Al dat nu downloadt van de relatief trage Xilinx-server. Voor mij duurde de download net meer dan twee uur.
Nadat de installatie voltooid is, moet u testen of Vivado met succes in batch-modus start. Xilinx biedt een shell-script dat de omgeving voor u instelt. Voordat u Vivado kunt draaien, moet u het source commando gebruiken om de inhoud van het script in uw actieve shell te laden:
source /tools/Xilinx/Vivado/2019.2/settings64.sh
Dan bent u klaar om Vivado te draaien. Maar er is geen GUI-omgeving geïnstalleerd op uw server, dus moeten we het in batch-modus starten met dit commando:
Als Vivado start en direct afsluit zonder fouten af te drukken, is dat een indicatie dat Vivado alles heeft wat het nodig heeft, en bent u klaar om te gaan. Let op dat als u de onderstaande fout krijgt, het is omdat u het ncurses-compat-libs pakket niet hebt geïnstalleerd, zoals we bespraken aan het begin van deze sectie.
application-specific initialization failed: couldn't load file "librdi_commontasks.so": libtinfo.so.5: cannot open shared object file: No such file or directory
Vivado integreren in Jenkins
Om Jenkins voor Vivado voor te bereiden, moeten we enkele wijzigingen aanbrengen in de algemene instellingen. Ga naar Manage Jenkins->Configure System en controleer of alle standaardinstellingen voor u zinvol zijn.
Zoals ik eerder vermeldde, gebruikt Vivado veel RAM. Het resourcegebruik hangt af van uw doel-FPGA, en u kunt een indicatie krijgen van hoeveel u nodig hebt van de Xilinx Memory Recommendations pagina. Daarom raad ik aan dat u het standaardaantal parallelle jobs dat kan draaien verandert van 2 naar 1. Tenzij u enorme RAM-bronnen op uw VPS heeft toegewezen, wilt u waarschijnlijk # of executors op 1 zetten, zoals in de afbeelding hieronder getoond.
In plaats van omgevingsvariabelen in elke Jenkins-job te definiëren, zullen we de PATH globaal specificeren voor alle jobs. Dat maakt het gemakkelijker om in de toekomst over te schakelen naar een nieuwere versie van Vivado. Dan kunt u verwijzen naar de 'vivado' executable in uw scripts, en het zal altijd wijzen naar de nieuwste versie, of welke u ook kiest.
Scroll naar de Global properties sectie en vink Environment variables aan. Klik Add om een nieuwe entry te krijgen. Zorg ervoor dat u de standaard Linux PATH ook opneemt. Ik gebruikte "PATH=/tools/Xilinx/Vivado/2019.2/bin:/sbin:/usr/sbin:/bin:/usr/bin", zoals in de afbeelding hieronder getoond.
Vergeet niet om naar beneden te scrollen en op Save te klikken.
Vivado GUI-projecten in batch-modus
Ik koos ervoor om de Vivado-projecten in GUI-modus te beheren. Voor elke repository creëerde ik een nieuw project vanuit de reguliere Vivado GUI, bronbestanden toevoegend, bibliotheken instellend, en al dat. Echter, de .xpr projectbestanden zijn binair en afhankelijk van veel andere tijdelijke bestanden in de projectmap.
Binaire bestanden zijn niet geschikt voor SCM's zoals Git. Gelukkig heeft Xilinx hieraan gedacht en een richtlijn (XAPP1165) geschreven voor hoe Vivado te gebruiken met versiebeheersystemen. Wat we doen is de write_project_tcl commando in Vivado gebruiken om het hele project te exporteren naar een Tcl-script. Het script bevat menselijk-leesbare Tcl-code geschikt voor Git.
Ik heb alle Git-repo's georganiseerd zodat alle bestanden die bij de Vivado-projecten horen in een submap genaamd "vivado" zitten, terwijl de VHDL-bronbestanden in de bovenliggende map zitten. Bekijk het demo packages-project op mijn GitHub om te zien wat ik bedoel. Voor elke repo zullen we de Vivado Tcl-scripts in de vivado map zetten. U zult ook het create_vivado_proj.tcl bestand vinden, wat de menselijk-leesbare versie van het Vivado-project is.
Om het create_vivado_proj.tcl bestand te maken, begin met het opzetten van het Vivado-project zoals u wilt in de Vivado GUI. Zorg ervoor dat het Vivado-project binnen een vivado submap woont. Wanneer u tevreden bent met het project, exporteer het door de volgende commando's in te voeren in de Vivado Tcl-console:
cd [get_property DIRECTORY [current_project]] write_project_tcl -force -target_proj_dir . create_vivado_proj
Voeg het create_vivado_proj.tcl bestand toe aan Git, en stel de gitignore in om de rest van het Vivado-project te negeren. Hier is de inhoud van mijn .gitignore bestand dat alles negeert behalve Tcl-scripts in de vivado map:
Het Vivado-project openen in batch-modus
Het is een goed idee om het Vivado-project handmatig op de VPS te testen voordat u begint met het aanmaken van Jenkins-jobs. Standaard draait de daemon vanaf een gebruikersaccount genaamd jenkins op de Linux-server. Daarom moet u het Vivado-project testen met de jenkins gebruiker.
Zorg ervoor dat u Git op de Linux-server hebt geïnstalleerd voordat u dit experiment start. Voer dit commando uit om Git te installeren na inloggen als root:
U kunt niet direct inloggen op de jenkins gebruiker, maar u kunt ernaar overschakelen vanaf de root-gebruiker als volgt:
Als u nu een pwd commando uitvoert, ziet u dat u bent op /var/lib/jenkins:
[jenkins@jenkins ~]$ pwd /var/lib/jenkins
Dat is omdat dit geen gewoon gebruikersaccount is dat de home-directory onder /home heeft, zoals de norm op Linux-systemen. Het is alleen voor het draaien van de Jenkins-daemon, maar we kunnen inloggen om een handmatige walkthrough van het buildproces in de Jenkins-omgeving te doen.
De home-map is vol met alle dynamische data zoals logs, gebruikersinstellingen en plugins die u hebt gedownload. Wanneer we later jobs in de Jenkins GUI gaan draaien, zullen ze in de jobs map verschijnen.
Laten we naar de jobs map gaan om ons experiment uit te voeren:
cd /var/lib/jenkins/jobs/
U kunt uw Git-repository direct in de jobs map klonen. Uw Git-repo moet toegankelijk zijn zonder wachtwoord te gebruiken. Ofwel omdat het publiek is, ofwel omdat u wachtwoordloze inlog hebt ingesteld zoals beschreven op de GitHub-hulp-pagina's.
Als u geen Git-repository met het Vivado-project gereed heeft, voel u vrij om een van mijn repo's te klonen als volgt:
git clone https://github.com/jonasjj/Jenkins-demo-packages
Dan, cd in de nieuwe map van de Git-repository, en verder in de vivado map:
cd Jenkins-demo-packages/vivado/
Als u mijn voorbeeld heeft gedownload, zou u twee Tcl-bestanden vinden: create_vivado_proj.tcl en check_syntax.tcl. De eerste is het Vivado-project geconverteerd naar een Tcl-bestand, en de tweede is een script waar we nog niet over hebben gesproken. Het is voor het controleren van de syntaxis van VHDL-bestanden in het Vivado-project.
Voordat we een Vivado-commando kunnen uitvoeren, moeten we de PATH omgevingsvariabele in de huidige shell instellen. In Jenkins losten we dit op met Global properties, maar nu komen we niet via Jenkins, dus moeten we het setup-script van Xilinx sourcen als volgt:
source /tools/Xilinx/Vivado/2019.2/settings64.sh
Nu de vivado executable in ons pad zit, laten we beginnen met het hercreëren van het project. Dit is het commando om dat te doen wanneer Vivado in batch-modus draait:
vivado -mode batch -source create_vivado_proj.tcl
Nadat u Enter indrukt, zou u een heel boel Tcl-code naar de console moeten zien ge-echo'd. Het is de code voor het hercreëren van het Vivado-project die uitvoert. Als u geen duidelijke fouten zag, typ het commando "echo $?" in de terminal voordat u iets anders doet. De output zou 0 moeten zijn als alles goed ging, zoals we uit de onderstaande listing kunnen zien.
INFO: [Common 17-206] Exiting Vivado at Sun Apr 19 18:32:48 2020... [jenkins@jenkins vivado]$ echo $? 0
Het "echo $?" commando toont u de exit-status van het vorige commando dat u in Linux uitvoerde. Een exit-status van 0 betekent dat alles OK is, geen fout. Elke andere exit-status dan 0 is een indicatie van fout. Dat zijn oude Unix-conventies waar u meer over kunt lezen hier. Toch is de exit-status belangrijk voor Jenkins omdat dat is hoe het besluit of een job-fase een succes of een falen is.
Als u nu een directory-lijsting doet, zult u zien dat Vivado de binaire bestanden van het project heeft hercreëerd:
[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
Laten we een ander experiment proberen met Tcl-scripts draaien in Vivado batch-modus. Maak een one-liner Tcl-script met het volgende commando:
Voer nu het script uit in Vivado batch-modus:
vivado -mode batch -source test.tcl
Nadat Vivado sluit, controleer de exit-code nogmaals met het "echo $?" commando:
[jenkins@jenkins vivado]# echo $? 1
Het is 1, wat exit-failure betekent in Unix. Als u de inhoud van het test.tcl-script wijzigt in "exit 0", en Vivado nog een keer draait, zult u zien dat de exit-status nu 0 is, wat succes aangeeft. Probeer het!
Het exit-trefwoord is standaard Tcl. We gaan het gebruiken als de interface tussen Vivado en Jenkins. Jenkins draait welk Tcl-script we ook creëren in Vivado, en kijkt naar de exit-status om te beslissen of het de job-fase als succes of falen moet markeren.
Vergeet niet ons kleine testproject uit de jobs-map te verwijderen wanneer u tevreden bent met het experiment:
cd /var/lib/jenkins/jobs/ [jenkins@jenkins jobs]# rm -rf Jenkins-demo-packages
Tcl-script voor het controleren van codesyntaxis in Vivado
Dit Tcl-script voert een syntaxiscontrole uit van de VHDL-bestanden in het project. Als u gaat simuleren of implementeren, hebt u dit script niet nodig omdat eventuele syntactisfouten de compilatie zullen breken. Maar voor mijn packages-project heeft het geen zin om een testbench te maken. De bevatten alleen constanten en type-declaraties. Ik wil nog steeds coderingsfouten vangen die naar deze repo worden gepusht, en dat is waar de syntaxiscontrole handig is.
In het script dat hieronder wordt getoond, beginnen we met het openen van het projectbestand. Dan roepen we het Vivado check_syntax commando aan terwijl we het vertellen de output op te slaan in een variabele genaamd msg. Na voltooiing van de controle kijken we naar het outputbericht om te zien of er fouten gerapporteerd zijn. Als check_syntax iets rapporteerde, stellen we de exit-status in op 1 (fout). Als er geen fouten waren, sluiten we af met 0 (succes).
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 ondersteunt alle standaard Tcl-trefwoorden, en er zijn ook veel ingebouwde commando's zoals check_syntax. Ik raad aan eens te kijken naar deze twee Xilinx-documenten die de Tcl-scripting-mogelijkheden in detail dekken:
Vivado Design Suite Tcl Command Reference Guide (UG835)
Vivado Design Suite User Guide Using Tcl Scripting (UG894)
Tcl-script voor simuleren in Vivado
Het volgende script dat ik creëerde is voor het draaien van de testbench in batch-modus. Hiervoor moet u de simulatiesets in de Vivado GUI configureren voordat u het project exporteert naar Tcl. Ga uw gang en hercreëer een van de simulatieprojecten op uw desktopcomputer met het create_vivado_proj.tcl script om te zien hoe ik het van tevoren had ingesteld. U kunt de gereconstrueerde projecten in de Vivado GUI openen.
Zoals u uit de onderstaande listing kunt zien, begin ik met het openen van het project. Dan stel ik de naam van de simulatie-fileset in een variabele (meestal sim_1). Na het lanceren van de simulatie moeten we het ook sluiten. Anders krijgt de status van de simulatie niet geschreven naar de logbestanden.
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]
Ik worstelde om een goede manier te vinden om de simulatiestatus te krijgen. Mijn VHDL-testbenches beëindigen op een VHDL finish trefwoord bij succes. Fouten resulteren in een VHDL-assertion-failure. Er is geen duidelijke manier om te achterhalen waarom de simulator stopte met Tcl-commando's in Vivado.
Gelukkig is Tcl een krachtige scripttaal. Mijn workaround is om de simulatie-log te openen en te zoeken naar de string "Failure:", wat een VHDL-assertion-failure aangeeft. Ten slotte sluiten we af met 1 als het woord in de log zit, of 0 als het er niet in zit.
Tcl-script voor synthetiseren in Vivado
In het Tcl-script voor synthetiseren in Vivado batch-modus, beginnen we met het openen van het projectbestand. Dan wijzen we de run-naam toe aan een variabele. U moet de ontwerpbestanden aan het Vivado-project hebben toegevoegd voordat u het exporteerde naar Tcl. Als u de naam van de synthetiseringsrun in de GUI niet veranderde, is het waarschijnlijk "synth_1".
U moet de CPU-tel-variabele instellen op het aantal logische processors dat uw server heeft. Dit getal controleert de mate van multithreading die Vivado gebruikt. Ik koos voor de VPS met 4 CPUs op UpCloud, en stelde daarom de CPU-tel in op 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 Het launch_runs-commando is non-blocking, wat betekent dat het voltooid voordat de echte synthetisering. Als we proberen de status direct na het aanroepen van launch_run te lezen, zal het "Running" zijn. Om het script te pauzeren tot de synthetisering voltooid is, roepen we het wait_on_run commando aan.
Ten slotte halen we de run-status op en sluiten we af met 0 of 1, afhankelijk van het statusbericht.
Tcl-script voor het uitvoeren van de implementatie in Vivado
Het script voor het uitvoeren van Place and Route (PAR) in Vivado batch-modus is vergelijkbaar met het synthetiseringsscript. Het verschil is dat de run-naam nu "impl_1" is, en dat we naar een ander succesbericht kijken.
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 voor het genereren van de bitstream in Vivado
Ten slotte, na als de implementatie met succes voltooit, kunnen we een bitstream genereren voor het programmeren van de FPGA. Het script is vergelijkbaar met de vorige, maar het launch_runs commando is iets anders. En natuurlijk kijken we naar een andere status aan het eind.
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 De Jenkins-jobs instellen
Een job in Jenkins verwijst naar een set gegroepeerde softwaretaken. Jenkins toont jobs en hun huidige status als items in een lijst op de overzichtspagina. U kunt jobs handmatig starten vanuit de webinterface, of ze kunnen automatisch getriggerd worden, bijvoorbeeld wanneer iemand code pusht naar een repo, of als resultaat van een andere job die voltooit. We zullen beide doen.
Jenkins biedt verschillende manieren om jobs te beheren. De traditionele methode is het Freestyle project, waar u elke actie specificert vanuit de Jenkins web GUI. De modernere manier om Jenkins-jobs te beheren is een pipeline-script te gebruiken dat alle informatie over de uitvoeringsstroom opslaat. Pipeline-scripts hebben het voordeel dat u ze aan uw SCM kunt toevoegen.
Om een nieuw pipeline-script te maken, selecteer New item uit de Jenkins-zijbalk. In het dialoogvenster dat opent, selecteer de Pipeline optie en klik OK, zoals in de afbeelding hieronder getoond.
Het eerste wat we in de job-configuratie moeten doen is de GitHub-repository toevoegen die de broncode bevat. In dit voorbeeld gebruik ik de packages-repo, maar de procedure is hetzelfde voor alle andere jobs en repo's. Vink het GitHub project vakje aan en voer het adres in het Project url veld in dat verschijnt, zoals in de afbeelding hieronder getoond.
Daarna kunnen we de build-triggers voor deze job instellen. Ik wil dat deze job start wanneer iemand code pusht naar de GitHub-repo. Om dat te doen, vinken we het vakje aan dat zegt GitHub hook trigger for GITScm polling, zoals in de afbeelding hieronder getoond. Let op dat dit alleen werkt als u het Manage hooks vakje in de globale instellingen heeft aangevinkt, zoals we eerder deden.
Onder aan de job-configuratiepagina is de Pipeline sectie. Hier heeft u de optie om het pipeline-script direct in de configuratiepagina in te voeren. Maar we willen het pipeline-script versiebeheren. Daarom kiezen we de Pipeline script from SCM optie. Zorg ervoor dat Git geselecteerd is, zoals in de afbeelding hieronder getoond.
Plak de URL van uw GitHub-repository in, en selecteer uw referenties als het een privés repo is. De onze is publiek, dus we laten de referenties leeg. We gaan ook met de standaard master-branch selectie.
Ten slotte moeten we het pad naar het Jenkins-script binnen de Git-repository selecteren. Ik heb een bestand genaamd Jenkinsfile aan de root van elke repo aangemaakt. Vergeet niet op Save te klikken voordat u de pagina verlaat.
Jenkins pipeline-scripts
Pipeline-scripts volgen dezelfde syntaxisregels als de Apache Groovy programmeertaal, wat ik moet toegeven dat ik nooit van had gehoord. Toch zult u geen moeite hebben pipeline-scripts te begrijpen als u enig soort moderne programmering heeft gedaan. Op het eerste gezicht ziet het eruit als een JSON-schema zonder de komma's die de data-items scheiden.
De scripts zijn tamelijk veelzijdig, en er zijn veel opties voor dingen zoals fasen parallel uitvoeren of taken draaien op meerdere Jenkins-servers. Ik stel voor dat u eens kijkt naar de officiële Jenkins pipeline-documentatie als u dieper in de materie wilt duiken.
Gelukkig hoeft u niet alles over ze te weten om te profiteren van pipeline-scripts. We zullen het onderstaande formaat als sjabloon gebruiken voor al uw scripts. We zullen zoveel fasen toevoegen als we nodig hebben om de job in logische stappen te splitsen.
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' } } } Als iemand foutieve code naar de repo pusht, willen we dat de schuldige een geautomatiseerde e-mail ontvangt met informatie over de mislukte job. Om dat te doen, gebruiken we een failure sectie binnen een post sectie. Dit deel van het script zal alleen uitvoeren als een van de fasen faalt. Dan stopt de job. Jenkins gaat niet naar de volgende fase als er een faalt. In plaats daarvan springt het in de failure sectie. Jenkins haalt de e-mailadressen op uit de laatste Git-commits en stuurt ze een e-mail met een link naar de gebroken build.
VHDL-syntaxiscontrole job
De enige repo in ons ontwerp die geen testbench heeft is de packages-repo—instead gebruiken we ons check_syntax.tcl script om te verifiëren dat de code ten minste geldig VHDL is.
In de eerste stap van ons pipeline-script roepen we deleteDir() aan. Dat is een van de basiscommando's beschikbaar in Jenkins pipeline-scripts. Het schoont de werkmap op door eventuele restanten van eerdere builds te verwijderen.
Op de volgende regel roepen we git aan. Let op dat dit niet het git Linux-commando is, maar een commando dat verwijst naar de git Jenkins-plugin. We vertellen het de repository te klonen in de werkruimte.
Ten slotte, op de derde regel van de Create project fase, gebruiken we het sh-trefwoord om een Linux-shellcommando aan te roepen. Hier veranderen we naar de vivado map en draaien we het create_vivado_proj.tcl script in Vivado batch-modus om het Vivado-project te hercreëren.
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 de tweede fase, degenaamde Check VHDL syntax, bestaat het Vivado-project al, dus kunnen we springen naar het draaien van ons Tcl-script. We gebruiken het shell-commando weer om het check_syntax.tcl bestand uit te voeren, wat met 0 afsluit bij succes, of 1 bij fout, wat Jenkins de build als mislukt markeert.
VHDL-simulatie-jobs
Voor alle andere jobs dan de packages-repo, werkt de git one-liner-commando niet voor het uitchecken van de code van GitHub. Het probleem is dat deze repo's afhankelijkheden hebben in de vorm van submodules. De submodules refereren naar andere Git-repositories, wat het simpele git commando niet standaard ophaalt. Maar dat is OK; we kunnen het probleem oplossen door de meer veelzijdige checkout aanroep te gebruiken, ook goed gedocumenteerd op de Git-plugin-pagina.
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' } } } Ten slotte draaien we het run_simulation.tcl script in Vivado in de volgende fase.
De bovenstaande listing toont het script dat gebruikt wordt in de bcd_encoder repo. Identieke scripts, alleen met verschillende repo-URL's, worden gebruikt voor de counter, digit_selector, output_mux, reset, en seg7_encoder repo's ook.
FPGA-implementatiejob
De seg7-repo bevat de top-module voor ons FPGA-project. Het haalt alle andere repo's binnen als submodules. Het pipeline-script is vergelijkbaar met het script gebruikt voor de simulatie-only jobs, maar met vier toegevoegde fasen: Run simulation, Run implementation, Generate bitstream, en Release bitfile.
De eerste twee fasen creëren het project en draaien de simulatie. Ik heb al uitgelegd hoe ze werken in de vorige secties van dit artikel. De volgende drie fasen werken op dezelfde manier als de simulatie-fase, maar met het Tcl-script vervangen door degenen die relevant zijn voor de taak.
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' } } } De laatste fase van de implementatiejob heet Release bitfile. Het bevat een shell-script dat de zojuist gegenereerde FPGA-programmeerbestand kopieert naar een release-map. Het shell-commando hernoemt het bestand om de naam van het project en een timestamp te bevatten.
Voor traceerbaarheid genereren we ook een tekstbestand dat de Git-hash van de hoofd-repo (seg7) en alle submodules bevat. Bij het werken met Git-submodules is het niet genoeg om de hash van de hoofd-repo op te slaan. Om een hash voor de hoofd-repo te genereren die wijzigingen in alle submodules omvat, zouden we de hoofd-repo moeten committen na het ophalen en bijwerken van alle submodules. We willen dat niet automatisch vanuit Jenkins doen.
Let op dat het implementeren van de FPGA voor elke push, zoals ik in het voorbeeld doe, waarschijnlijk niet wat u wilt voor een echte Jenkins-project. Het kan uren duren om een grootschalig FPGA-project te bouwen, en dat zou niet werken wanneer u een team van ontwikkelaars heeft die meerdere keren per dag pushen. In plaats van te bouwen na elke push naar de repo, kunt u Jenkins configureren om de FPGA maar één keer per dag te routeren. Bijvoorbeeld, om middernacht, zoals getoond in de onderstaande screenshot van de job-configuratiepagina.
Builds triggeren na voltooiing van andere jobs
Ons voorbeeldproject bestaat uit verschillende Git-repositories, maar ze zijn allemaal verbonden als Git-submodules. Behalve packages, zijn alle andere repo's afhankelijk van ten minste één andere repository. Meeste zijn afhankelijk van de packages-repository. Kijk naar de afhankelijkheidsgrafiek die ik eerder in dit artikel presenteerde om te zien hoe het allemaal past.
Daarom moeten we jobs triggeren niet alleen door pushes naar de repo in kwestie, maar ook nadat een van de submodules wordt aangeraakt. We kunnen dit in Jenkins bereiken door elke job te bezoeken en de Build after other projects are built optie dienovereenkomstig in te stellen.
De afbeelding hieronder toont de trigger voor het bcd_encoder-project. Het start na de packages-repo, waar het van afhangt, een build succesvol voltooit.
De top-module is afhankelijk van alle andere repo's. Ik heb ze toegevoegd als watch-projects in een komma-gescheiden lijst, zoals in de afbeelding hieronder getoond. Let op dat u dit misschien niet wilt doen voor de FPGA-implementatiejob als het lang duurt om te routeren, zoals ik in de vorige sectie vermeldde.
De bitfiles serveren met Nginx
Omdat we al een webserver draaien, kunnen we die gebruiken voor het serveren van de releasebestanden via HTTP. Ik wil dat alle nieuwe bitfiles verschijnen op de URL jenkins.vhdlwhiz.com/releases. Laten we zien hoe we Nginx hiervoor kunnen gebruiken.
Onze implementatiejob kopieert nieuwe bitfiles al naar een map op de Nginx HTML-root, maar we hebben die nog niet aangemaakt. Maak de release-dir aan en geef de Jenkins-gebruiker schrijfrechten door de volgende commando's uit te voeren:
mkdir /usr/share/nginx/html/releases/ chown jenkins.root /usr/share/nginx/html/releases/
Dan moeten we een wijziging aanbrengen in het /etc/nginx/nginx.conf bestand. Zoek de serversectie in het configuratiebestand met een naam gelijk aan uw domein. Voeg de volgende location-sectie toe binnenin, direct onder de root ('/') location-sectie:
location ^~ /releases { alias /usr/share/nginx/html/releases/; autoindex on; } Ten slotte, nadat u het bestand heeft opgeslagen, test het configuratiebestand, en herlaad de Nginx-server:
nginx -t systemctl reload nginx
Als alles werkte, zou u de inhoud van de release-map moeten kunnen lijsten, zoals in de onderstaande screenshot uit Google Chrome getoond.
Om de Jenkins-webinterface te koppelen aan de release-dir, wil ik een link naar het vanuit de Jenkins-zijbalk maken. We hebben al de Sidebar Link-plugin geïnstalleerd die aangepaste links in de zijbalk mogelijk maakt.
De volgende stap is om naar Manage Jenkins->Configure System te gaan en naar beneden te scrollen naar de Additional Sidebar Links sectie. Hier kunnen we de naam en URL van de nieuwe link specificeren, zoals in de afbeelding hieronder getoond. Het link-icoon-veld is optioneel. Ik hergebruikte een van de iconen die bij de Jenkins-server kwamen.
Na het voltooien van de vorige stap, zou u nu een aangepaste link naar de bitfile-releases in de zijbalk moeten hebben, complete met een mooi map-icoon, zoals u kunt zien in de afbeelding hieronder.
Samenvatting
Jenkins kan een waardevol hulpmiddel zijn voor FPGA-teams. Het automatiseren van taken kan uw bedrijf tijd besparen en de kwaliteit van uw code verbeteren. Door gebruik te maken van automatische build-triggers en geautomatiseerde job-pipelines, zullen minder coderingsfouten onopgemerkt blijven.
Zoals we hebben gezien uit het voorbeeldproject dat in dit artikel gepresenteerd wordt, kan Jenkins een complete suite van regressietesten implementeren voor uw VHDL-code. Het toont de huidige gezondheid van uw project in een prettige grafische webinterface, geschikt voor zelfs de meest VHDL-onwetende projectmanager.
Als u Jenkins voor FPGA-ontwikkeling wilt uitproberen, raad ik aan de stappen in dit artikel te volgen op een UpCloud VPS-instantie. Ik heb alle VPS-providers grondig onderzocht een paar jaar geleden voordat ik VHDLwhiz naar een VPS verhuisde. Ik vond dat UpCloud de snelste en beste alternatief was. Ik ben nog steeds 100% tevreden met de dienst.
Als u besluit een account aan te maken op UpCloud, vraag ik u vriendelijk mijn verwijzingslink of code te gebruiken: NV78V6. Niet alleen steunt u VHDLwhiz, maar u krijgt ook $25 tegoed op UpCloud bij het gebruik van de promotiecode.
VHDL
- Signed vs. Unsigned Typen in VHDL: Praktische Inzichten
- Een PWM-controller implementeren in VHDL: Ontwerp, Simulatie en FPGA-demo
- Signed en unsigned types in VHDL onder de knie krijgen: een praktische gids
- Test je VHDL-basis – Interactieve Quiz Deel 1
- VHDL-functies onder de knie krijgen: een praktische gids voor efficiënt ontwerp
- Een dynamische gelinkte lijst in VHDL implementeren met protected types en access pointers
- Constrained Random Verification onder de knie met OSVVM
- Stapsgewijze Handleiding: Je Eerste FPGA LED-knipperder Bouwen
- Loop- en Exit-constructs in VHDL: Een praktische gids
- Een klokgetriggerd proces in VHDL bouwen: een praktische gids
- Wat is VHDL? Een praktische gids voor Hardware Description Language