Sbloccaggio delle prestazioni FPGA con Sintesi ad alta velocità

Le versioni di HPG (HG) hanno richiesto tradizionalmente una profonda esperienza nelle lingue di descrizione hardware (HDL) come VHDL e Verilog. High-Level Synthetic (HLS) gira quel modello, permettendo agli sviluppatori di scrivere algoritmi in C, C++, o SystemC e genera automaticamente il codice RTL ottimizzato. Questo spostamento rende lo sviluppo FPGA accessibile agli ingegneri del software, mentre slash iteration cycles.

Che cosa è la sintesi di High-Level?

La sintesi di alto livello è un processo di compilazione che converte una descrizione comportamentale non prestabilita – in genere in C/C++ – in un'implementazione hardware tempestiva. A differenza dei compilatori software che mirano a un set di istruzioni fisso, HLS deve programmare le operazioni in cicli di clock, assegnare unità funzionali, legare le operazioni a specifiche risorse hardware e generare una macchina a stato finito con vincoli di dati.

Il vantaggio critico è l'astrazione: loop, array e chiamate di funzione sono sintetizzati direttamente senza dover creare macchine statali o percorsi dati pipelining. Lo strumento inferisce il parallelismo, genera protocolli di interfaccia e ottimizza la condivisione delle risorse. Ad esempio, la stessa funzione C può mappare un'interfaccia AXI4-Stream, uno slave AXI4 mappato dalla memoria, o entrambi, semplicemente cambiando il programma.

Scegliere lo strumento giusto HLS

Sono disponibili diversi strumenti HLS maturi, ciascuno strettamente integrato con un ecosistema di fornitori o offerti da aziende EDA di terze parti. La selezione dipende spesso dalla famiglia di dispositivi di destinazione e dalla complessità di progettazione.

  • AMD Vitis HLS (ex Vivado HLS):] La nave ammiraglia per i dispositivi AMD Xilinx, supportando la sintesi del kernel C, C++ e OpenCL. Genera RTL che collega direttamente al Vivado IP integrator e funziona senza soluzione di continuità con la piattaforma software unificata Vitis per applicazioni accelerate.
  • Intel High-Level Synthetic Compiler (HLS Compiler):] Integrato in Intel Quartus Prime, questo strumento sintetizza C++ per Intel Agilex, Stratix e Arria FPGAs. Eccellente a datapath-intensive disegni e supporta il parallelismo delle attività e la pipelining del loop fine-grained.
  • Siemens Catapult HLS:[] Uno strumento diagnostico del fornitore che sintetizza da SystemC o C++ per obiettivi ASIC e FPGA. È ampiamente utilizzato nelle applicazioni aerospaziale e automotive e offre un controllo formale dell'equivalenza, rendendolo adatto per sistemi critici per la sicurezza.
  • Opzioni di apertura:] Lo strumento Bambu HLS del Politecnico di Milano è un framework open source attivamente mantenuto che accetta la norma C e genera Verilog.

Ogni strumento ha la sua sintassi pragma e la filosofia di ottimizzazione, ma i concetti HLS core rimangono coerenti. Gli esempi in questo articolo si concentrano sugli strumenti forniti dal fornitore ma si applicano in larga misura su piattaforme.

Il flusso di progettazione basato su HLS

L'adozione di HLS significa passare da un flusso di lavoro RTL-centrico a un ciclo software-come di codifica, simulazione e raffinatezza incrementale.

Passo 1: Specificazione dell'algoritmo e convalida C-Level

Iniziare implementando il vostro algoritmo interamente in C o C++ come un "modello d'oro". Questo modello dovrebbe essere bit-accurato e auto-controllo, con vettori di prova che coprono tutti i casi di angolo. Poiché la sintesi HLS è sensibile allo stile di codifica, separare la funzionalità sintetizzabile da non-synthesizable codice di prova, tipicamente mettendo il core algoritmo in una funzione dedicata.

Convalida il modello dorato con compilazione e simulazione C standard (ad esempio, utilizzando GCC o MSVC). Questo cattura errori algoritmici presto, molto prima che la simulazione hardware inizi. Lo strumento HLS utilizzerà in seguito lo stesso banco di prova per la co-simulation C/RTL, quindi lo sforzo di investimento qui paga con bellezza.

Passo 2: Configurazione degli strumenti e Specificazione del bersaglio

Creare un nuovo progetto HLS nel tuo strumento scelto (Vitis HLS, Intel HLS Compiler, ecc.).

  • La funzione superiore per sintetizzare.
  • La parte o la scheda FPGA di destinazione, che determina le risorse disponibili, la frequenza di clock e l'architettura dei dispositivi.
  • Il limite di tempo di orologio, tipicamente nei nanosecondi, questo spinge le decisioni di pianificazione e pipelining.
  • Impostazioni di simulazione e, per Vitis HLS, se utilizzare la simulazione C o la co-simulation con un simulatore RTL esterno.

Una corretta configurazione garantisce l’allineamento delle ottimizzazioni dello strumento con le capacità di temporizzazione fisica. Un errore comune sta impostando un periodo di tempo di clock eccessivamente ottimistico, causando guasti di sintesi in seguito. Inizia con un obiettivo conservatore (ad esempio, 10 ns / 100 MHz) e stringe gradualmente dopo la revisione dei rapporti di programmazione.

Passo 3: Ottimizzazione del codice utilizzando Pragma e direttive

I pragmi sono il meccanismo primario per guidare lo strumento HLS. Senza di loro, lo strumento sintetizza un design sicuro ma sotto-ottimizzato— loop sequenziali, risorse completamente condivise, parallelismo minimo.

  • Più possibile la tubatura:[ ] causa la sovrapposizione delle iterazioni a ciclo, iniziando una nuova iterazione ogni II (intervallo di iniziazione) cicli. Un condotto II=1 fornisce un risultato per ciclo di orologio dopo latenza iniziale, massimizzando il throughput.
  • Loop unrolling:[ replica i corpi a loop per eseguire più iterazioni in parallelo, scambiando l'area per le prestazioni.
  • Il partizionamento e la rimozione dell'Array:[ []] divide gli array in banche di memoria più piccole per l'accesso parallelo. ] combina i dati divisi in una parola di memoria più ampia.
  • Inlineazione di attivazione:[ ] si fonde con le gerarchie della funzione, dando allo strumento più spazio per l'ottimizzazione transfrontaliera.
  • Interfaccia pragma:[] Specificare come la funzione superiore si collega— per lo streaming, per un'interfaccia di controllo mappata dalla memoria, per l'accesso alla memoria DDR esterno, ecc.
  • Dataflow:[ [] consente il parallelismo a livello di attività, permettendo una sequenza di funzioni o loop di funzionare contemporaneamente come un condotto con canali di streaming.
  • Risorsa allocazione:[] []] o [[]]] le direttive possono limitare il numero di DSP o porte di memoria, impedendo la contention delle risorse.

I pragma ben scelti possono significare la differenza tra un design che incontra appena il throughput e uno che lascia le risorse inattivo. Il processo di ottimizzazione è iterativo: applicare direttive, sintetizzare, ispezionare le prestazioni e i rapporti di utilizzo e affinare.

Fase 4: Sintesi e analisi

La relazione più importante è il profilo delle prestazioni, mostrando la latenza di ogni ciclo, l’intervallo di iniziazione e la profondità delle tubazioni. Il rapporto di utilizzo delle risorse rompe LUT, infradito, DSP e blocca l’utilizzo della RAM.

Gli strumenti HLS moderni generano anche un visualizzatore di pianificazione (un grafico Gantt) e una mappa vincolante, aiutandovi a visualizzare come le operazioni sono distribuite in cicli di clock e unità funzionali. Se l'intervallo di iniziazione o la latenza raggiunta è più alto di quanto desiderato, cercare “dipendenze di punti di carico” o conflitti di porta di memoria contrassegnati nel rapporto.

Fase 5: C/RTL Co-Simulation

Prima di integrare la RTL generata in un design FPGA più ampio, verificare l'equivalenza funzionale attraverso la co-simulation. Lo strumento compila il banco di prova C originale contro il RTL generato utilizzando un simulatore bundle (ad esempio, Xcelium, ModelSim, o Vivado Simulator).

Se si verificano errori, ispezionare la forma d'onda o il registro delle transazioni. Regolare il modello C o pragma (ad esempio, aggiungendo con latenza appropriata) fino a quando il comportamento RTL corrisponde al modello d'oro-accuratamente.

Passo 6: Esporta IP e Integra nel flusso di progettazione FPGA

Una volta verificato, esportare il design come core IP confezionato – in genere in formato IP-XACT o Intel Qsys. Questo blocco IP può essere istantaneo in un design a blocchi (ad esempio, Vivado IP Integrator) insieme ad altri moduli RTL, processori morbidi o controller di memoria. L'IP generato da HLS include vincoli di temporizzazione ed è pronto per il posizionamento e il routing.

Nel flusso tradizionale FPGA, si esegue la sintesi e l'implementazione (place-and-route) per generare il bitstream finale. Monitorare attentamente i rapporti di implementazione dei tempi. Gli strumenti HLS forniscono tempistiche stimate in base ai modelli di pre-placement; il posizionamento reale può rivelare ritardi di instradamento più lunghi, che richiedono di rilassare l'orologio di destinazione o rivisitare i vincoli HLS.

Esempio pratico: Implementare un filtro FIR con HLS

Per solidificarli, consideri un filtro a risposta a impulsi finiti (FIR) – un blocco comune di elaborazione del segnale digitale. Il codice C sottostante implementa un filtro FIR da 16 giri con coefficienti a punto fisso.

#include <ap_fixed.h>
#include <hls_stream.h>

typedef ap_fixed<16,8> data_t;
typedef ap_fixed<16,8> coeff_t;

void fir(hls::stream<data_t> &in, hls::stream<data_t> &out, coeff_t coeffs[16]) {
#pragma HLS INTERFACE axis port=in
#pragma HLS INTERFACE axis port=out
#pragma HLS INTERFACE s_axilite port=coeffs
 static data_t shift_reg[16];
#pragma HLS ARRAY_PARTITION variable=shift_reg complete dim=1
 data_t acc = 0;
 // Shift and accumulate
 ShiftLoop:
 for (int i = 15; i > 0; --i) {
#pragma HLS PIPELINE II=1
 shift_reg[i] = shift_reg[i-1];
 acc += shift_reg[i] * coeffs[i];
 }
 shift_reg[0] = in.read();
 acc += shift_reg[0] * coeffs[0];
 out.write(acc);
}

Prefettura di questo esempio:

  • Asse INTERFACE:[] Utilizza AXI4-Stream per l'ingresso e l'uscita, ideale per il flusso continuo dei dati.
  • ARRAY PARTITION completo:[] Spacca il registro di spostamento in singoli registri, consentendo l'accesso parallelo a tutti i rubinetti.
  • PIPELINE II=1:[] Assicura che un nuovo campione venga elaborato per ciclo di orologio dopo la latenza iniziale.

Dopo la sintesi, controllare i report: il loop di spostamento dovrebbe raggiungere II=1, e l'utilizzo delle risorse (DSP per moltiplicazioni) dovrebbe allinearsi a 16 moltiplicatori. Questo design viene poi esportato come nucleo IP e integrato in un sistema più grande, ad esempio, collegato ad un DMA AXI per trasmettere i dati da un sensore.

Strategie di ottimizzazione per prestazioni e area

L'HLS efficace richiede un bilanciamento del throughput, della latenza e del consumo di risorse.

  • Preferire aritmetica a punto fisso:[[] Le operazioni a punto di galleggiamento consumano risorse significative e frequenza di limite. A meno che la gamma dinamica non sia critica, utilizzare tipi a punto fisso (ad esempio, in Vitis HLS) per ridurre i conteggi DSP e LUT, preservando la precisione.
  • I dati standard invece di accesso casuale alla memoria:[ L'hardware è più efficiente quando i dati scorre attraverso una pipeline. Usa [] o simili costrutti di streaming per collegare le attività, evitando grandi memorie condivise che portano a banchi di arbitrato e buffer.
  • Cinchi a ciclo di studio per nidi a ciclo perfetto: Lo strumento può condurlo automaticamente. Assicurare che i loop non abbiano dipendenze a ciclo non oltre i modelli conosciuti (ad esempio, riduzione).Per la convoluzione o la matrice moltiplicare, considerare la memoria locale che buffering e la tiling per sfruttare il riutilizzo dei dati.
  • Utilizzare il metaprogrammazione del modello per la configurabilità:[[] I modelli C++ consentono la parametrizzazione a tempo di compilazione delle dimensioni e delle larghezze dei dati, rendendo la stessa sorgente HLS riutilizzabile su dispositivi senza perdita di prestazioni.
  • La condivisione delle risorse di equilibrio e la latenza:[ La direttiva [ può forzare la condivisione di operatori costosi come divisori. Tuttavia, la sovra-condivisione può serializzare operazioni e aumentare la la latenza; pesare contro le prestazioni del gasdotto.
  • Leverage bit-accurate tipi saggiamente:[] Utilizzando rappresentazioni a punto fisso strettamente digitate minimizza i costi dell'hardware. Ad esempio, per i dati dei pixel utilizza risorse minime mantenendo la precisione necessaria.

Gli strumenti HLS offrono anche directory “soluzione” dove è possibile mantenere più set di ottimizzazione (ad esempio, “bassa area”, “alta produttività”) e confrontarli.

Debug e verifica Migliori Pratiche

Poiché il codice sorgente è C++, i tradizionali debugger possono convalidare la funzionalità, ma non possono rivelare parallelismo hardware o bug di temporizzazione. Le seguenti pratiche riducono il dolore:

  • Mantenere un modello C++ puro di tipo ciclo-approximate che utilizza gli stessi protocolli di interfaccia (ad esempio, streaming) in modo da poter simulare velocemente.
  • Implement auto-controllo banchi di prova con generazione di input randomizzata e uscite di riferimento dorate.
  • Utilizzare il log dello strumento HLS e le avvertenze pragma aggressivamente. Trattare i costrutti non-synthesizable o strutture a ciclo sub-ottile come errori.
  • Iniziare la co-simulation presto su un piccolo sub-modulo prima di scagliare al disegno completo.
  • Utilizzare l'analisi delle prestazioni integrata dello strumento HLS per visualizzare i colli di bottiglia di intervallo di iniziazione prima di eseguire lunghe simulazioni RTL.
  • Ispezionare il codice RTL generato per strutture inattese: ad esempio, i grandi multiplexers spesso indicano rami condizionali eccessivamente complessi. Semplifica i condizionali mediante l'appiattimento nidificato dichiarazioni, laddove possibile.

Pitfalls comune e come evitare di loro

Anche gli ingegneri esperti incontrano problemi di ripetizione quando si spostano a HLS. Riconoscendoli in anticipo leviga la transizione.

  • Cuscite senza limiti:[] Le loops con conteggi variabili di viaggio che non sono calcolabili al momento del compilazione non possono essere pianificate correttamente.
  • Le grandi interfacce di memoria con scarsa larghezza di banda:[ Un'unica interfaccia AXI4-Lite master per grandi data arrays incollerà le prestazioni.Per un alto rendimento, utilizzare AXI4-Stream o AXI4 master con conversione di datawidth e supporto di scoppio, controllato da pragmas appropriati.
  • Ignorando reset e inizializzazione:[] A differenza di RTL puro, HLS a volte assume registri possono iniziare in uno stato valido. Assicurarsi di avere una strategia di reset pulita e evitare array locali non inizializzati che possono dedurre RAM non inizializzate (uso dove necessario).
  • Over-relying su strumento auto-ottimizzazione:[ Mentre gli strumenti HLS sono potenti, non possono indovinare l'intento di progettazione. Un semplice protocollo handshake potrebbe avere bisogno di esplicita interfaccia di selezione per abbinare il comportamento previsto; affidarsi a default può portare a interfacce mismatched.
  • Neglecting real-world vincoli di tempismo:[ La programmazione HLS utilizza un semplice modello di tempismo. Il posizionamento fisico di reti ad alta luminosità o di grandi multiplexers può causare violazioni inaspettate dei tempi.
  • Per verificare le bancarelle di tubazioni:[] In un loop conduttivo, se il flusso di ingresso si stacca, il gasdotto deve essere in grado di drenare senza lo sgancio.

Integrazione di HLS con sistemi eterogenei

Le piattaforme FLTA moderne accoppiano logica programmabile con sistemi di processore duri (ad esempio, ARM Cortex in Zynq, Agilex SoC). HLS si adatta naturalmente a queste architetture. Un modello comune è quello di utilizzare il processore per controllare e configurare un acceleratore generato HLS tramite AXI-Lite, mentre i flussi di dati ad alta banda tramite AXI4-Stream o AXI4F4

Per i sistemi di controllo in tempo reale, HLS può generare una periferica RTL personalizzata che si interfaccia con l'interconnessione AXI del processore, la gestione di I/O critico temporale mentre il processore gestisce politiche e stack di rete. Questa divisione del lavoro massimizza le prestazioni senza sacrificare la flessibilità.

Il futuro della sintesi di High-Level

L'HLS si sta rapidamente evolvendo, con miglioramenti nell'euristica del compilatore, nella verifica formale e negli ecosistemi della biblioteca.

  • L'apprendimento della macchina per l'autoML-style HLS:[] Gli strumenti stanno iniziando a incorporare modelli ML che prevedono configurazioni pragma ottimali, riducendo la messa a punto manuale.La ricerca sia dall'accademia che dall'industria mira a costruire la sintesi "push-button" che rivali design di esperti.
  • Standardization around C++17 e oltre:[] Poiché i front-end HLS adottano moderni standard C++, i progettisti possono sfruttare constexpr, lambdas e il metaprogramming del modello per scrivere librerie hardware altamente parametrizzate e riutilizzabili.
  • Integrazione dei clienti con verifica di alto livello:[[ Metodologia Universale di Verifica (UVM) e modellazione a livello di transazione SystemC sono in fase di combinazione con HLS per creare flussi di progettazione e verifica unificato, riducendo il collo di bottiglia di verifica.
  • Apri risorse stack hardware:[] Progetti come la [CHIPS Alliance[] stanno promuovendo i framework e le librerie HLS aperti, rendendo HLS più accessibile oltre i principali fornitori di FPGA.
  • L'aumento del supporto per la riconfigurazione dinamica:[ I flussi HLS futuri possono consentire lo scambio di kernel a tempo di esecuzione, consentendo sistemi adattativi che riconfigurano in risposta ai carichi di lavoro cambianti.

HLS offre un modo per gestire questa complessità aumentando il livello di astrazione mantenendo l'efficienza hardware. Mastering HLS ora posiziona gli ingegneri per costruire la prossima generazione di sistemi ad alte prestazioni, riconfigurabili, dagli acceleratori AI bordo alle apparecchiature di networking ad alta velocità.