[LNIV Xilinx](index.html) | Vitis HLS | [model](hlsModel.htm) | [simulacija](hlsSim.htm) | [sinteza](hlsSint.htm) Visokonivojska sinteza (High-Level Synthesis) je proces načrtovanja vezij, ki pretvori algoritem v jeziku C/C++ v model digitalnega vezja. Predstavili bomo osnovne korake dela z orodjem **Vitis HLS** različice 2025.1. Dodatne povezave: - AMD Xilinx [High-Level Design](https://www.xilinx.com/products/design-tools/vivado/high-level-design.html) - Vitis [2015.1 Downloads](https://www.xilinx.com/support/download/index.html/content/xilinx/en/downloadNav/vitis/2025-1.html) - Parallel Programming for FPGAs [The HLS Book](https://github.com/KastnerRG/pp4fpgas/raw/gh-pages/main.pdf) # Vitis 2025 ### Izdelava projekta Na računalniškem disku si pripravimo delovno mapo (workspace) v kateri bodo shranjeni naši projekti. Orodja Vitis in Vivado uporabljajo skripte, ki imajo težave s globokimi mapami in imeni map, ki vsebujejo presledke, šumnike in posebne znake. Omejitev ne velja le za projektno mapo, ampak za celotno pot do delovne mape. Primer delovne mape: C:\proj\andrej Znotraj delovne mape bomo imeli eno ali več projektnih map s komponento vezja. Mapa s komponento vsebuje model v jeziku C++, testno kodo, nastavitve in sintetizirane IP komponente (Solutions). Za izdelavo novega projekta izberemo v orodju Vitis **HLS Development** in *Create Empty HLS Component*. ![](./hls/GetStarted.png) Nastaviti moramo ime komponente in lokacijo delovne mape (npr. ale in C:\proj\andrej). Program nato ponuja možnost vključitve obstoječih datotek z nastavitvami in izvorno kodo, lahko pa ta del izpustimo in določimo le ciljno tehnologijo (zavihek Hardware, npr. xc7z010clg400-1). Projektne datoteke dodajamo in odpiramo v navigacijskem oknu VITIS EXPLORER. ![](./hls/VitisExplorer.png) Delovni koraki so v orodju Vitis HLS dosegljivi v navigacijskem oknu FLOW, kjer izvajamo: - simulacijo (C SIMULATION), kjer prevedemo in izvedemo simulacijski program skupaj s funkcijo oz. modelom vezja, - sintezo modela vezja (C SYNTHESIS), - povezano simulacijo (C/RTL COSIMULATION), kjer izvedemo simulacijski program skupaj s simulacijo sintetizirane funkcije, - pakiranje IP komponente (PACKAGE) za uporabo v Vivadu in - implementacijo s tehnološkimi koraki za vezja FPGA. ### Model vezja v jeziku C Postopek sinteze bomo predstavili na modelu preproste aritmetično-logične enote. Naredimo novo izvorno datoteko (Sources, New Source File, add.cpp) s funkcijo *ale()*, ki izračuna rezultat ene od treh operacij nad celoštevilskimi vhodnimi podatki: ```c #include "ale.h" DATA_T ale(DATA_T x, DATA_T y, OP_T op) { DATA_T z; switch (op) { case 0: z = x + y; break; // seštevanje case 1: z = x * y; break; // množenje case 2: z = x / y; break; // deljenje default: z = 0; } return z; } ``` Vhodni parametri in izhod predstavljajo priključke vezja. Podatkovne tipe DATA_T in OP_T definiramo v novi zaglavni datoteki (Sources, New Source File, add.h). Običajen podatkovni tip **int**, bi v vezju predstavljal 32-bitne vektorje. Velikost vektorjev in vezja za izvedbo operacij prilagodimo z uporabo celoštevilskih tipov poljubne ločljivosti, ki so na voljo v knjižnici *ap_int.h*. V zaglavni datoteki določimo 20-bitni tip **ap_int<20>** za vhode in izhode in 2-bitni nepredznačen **ap_uint<2>** za izbiro operacije: ```C #ifndef _ALE_H_ #define _ALE_H_ #include <ap_int.h> typedef ap_int<20> DATA_T; typedef ap_uint<2> OP_T; DATA_T ale(DATA_T x, DATA_T y, OP_T op); #endif ``` ### Sinteza Priprava na sintezo vezja: - v oknu VITIS EXPLORER izberemo ustrezno komponento, če vsebuje delovna mapa več komponent, - v nastavitvah shl_config.cfg določimo ime funkcije, ki jo bomo sintetizirali (npr. ale) ![](./hls/hls_config.png) V oknu FLOW poiščemo C SYNTHESIS in s klikom na **Run** izvedemo sintezo vezja. V tem koraku lahko še določimo ciljno tehnologijo in frekvenco ure. Če ure ne določimo, bo privzeta perioda 10 ns. Po uspešno opravljeni sintezi odpremo in pregledamo poročilo, ki podaja zmogljivost vezja, oceno porabe gradnikov, opis priključkov in povezav operacij z gradniki. ![](./hls/SumSynthesis.png) Sintetizator naredi vezje z gradniki ciljne tehnologije in razdeli zahtevnejše operacije na več ciklov ure. Vezje sestavljajo namenske enote (npr. množilniki v blokih DSP), kombinacijska logika (LUT), pomnilniki (BRAM) in flip-flopi (FF). Rezultat sinteze je model vezja z ocenjeno porabo tehnoloških gradnikov in časovno metriko: - *latenca* je število ciklov za izračun izhodnih vrednosti (en klic funkcije) - *interval* II (iniciacijski interval) je število ciklov do naslednje ponovitve funkcije Datoteke s sintetiziranim vezjem se na računalniku nahajajo v podmapah ...hls\syn (npr. C:\proj\andrej\ale\ale\hls\syn). Na rezultat sinteze vplivamo z dodatnimi navodili v obliki direktiv. Če naprimer želimo obdelavo vhodnih podatkov v vsakem, ki se spremenijo v vsakem ciklu ure, sintetiziramo vezje v cevovodni izvedbi (pipeline). Takšno vezje bo običajno porabilo več logičnih in pomnilnih gradnikov. Direktive lahko vnašamo neposredno v opis funkcije ali pa s pomočjo grafičnega urejevalnika. V zavihku *Directive* dodamo z desnim klikom na glavno funkcijo *ale()* direktivo PIPELINE. Po sintezi vezja se inteval zmanjša na 1 cikel za ceno večje površine vezja (več uporabljenih FF in LUT). ![](./hls/directive.png) ### Simulacija Delovanje funkcije z visokonivojskim modelom vezja preizkusimo s simulacijo v programskem jeziku, kjer pripravimo simulacijski program (Testbench). Simulacijski program vsebuje glavno funkcijo main() v kateri nastavlja vhodne parametre, kliče funkcijo in prikazuje, shranjuje ali celo avtomatsko preverja rezultate. Zaznano napako lahko javimo tako, da glavna funkcija vrne vrednost različno od 0. ```C #include "ale.h" using namespace std; int main() { DATA_T x, y, z; OP_T op; cout << "Test Bench " << endl; x=8; y=7; op=2; z=ale(x,y,op); cout << x << "," << y << ", op:" << op << " z = " << z << endl; return 0; } ``` Za demonstracijo naredimo preprost testni program v katerem pokličemo funkcijo in izpišemo rezultate. Pri op=2 bo rezultat izpis: <pre> Test Bench 8,7, op:2 z = 56</pre> V praksi bo program bolj zapleten in bo naredil veliko klicev funkcije z različnimi parametri. Poleg simulacije v programskem jeziku je po sintezi na voljo povezana simulacija (Cosimulation), kjer se simulacijski program poveže s simulatorjem sintetiziranega vezja. Če želimo opazovati časovni potek signalov (waveform) moramo ob zagonu izbrati shranjevanje poteka signalov, npr. priključkov vezja (v okencu *Dump Trace* izberemo: *port*). ![](./hls/aleSim.png) Shranjen potek signalov lahko opazujemo v simulatorju vezij, ki je del orodja **Vivado**. Odpremo ga z novo ikono *Wave Viewer*, ki se prikaže v orodni vrstici po uspešno opravljeni povezani simulaciji. Na simulaciji opazujemo signale vmesnika: *ap_start*, *ap_idle*, *ap_ready* in *ap_done*. Logična 1 na *ap_start* sproži začetek izvajanja funkcije, *ap_done* pa signalizira zaključek, ko lahko preberemo rezultat.