Table of Contents
Déverrouillage des performances de FPGA avec synthèse de haut niveau
Les cartes de porte programmables sur le terrain (FPGA) ont traditionnellement exigé une expertise approfondie dans les langages de description matérielle (HDL) comme VHDL et Verilog. La synthèse de haut niveau (HLS) retourne ce modèle, permettant aux développeurs d'écrire des algorithmes en C, C++ ou SystemC et de générer automatiquement un code RTL optimisé. Ce changement rend le développement FPGA accessible aux ingénieurs logiciels tout en réduisant les cycles d'itération du concept au matériel de travail.
Qu'est-ce que la synthèse de haut niveau?
La synthèse de haut niveau est un processus de compilation qui convertit une description comportementale non chronométrée, typiquement en C/C++, en une implémentation matérielle chronométrée. Contrairement aux compilateurs logiciels qui ciblent un ensemble d'instructions fixes, HLS doit programmer les opérations en cycles d'horloge, attribuer des unités fonctionnelles, lier les opérations à des ressources matérielles spécifiques, et générer une machine à état fini avec datapath.
L'avantage critique est l'abstraction : les boucles, les tableaux et les appels de fonctions sont synthétisés directement sans créer manuellement des machines d'état ou des datapaths de pipeline. L'outil infere le parallélisme, génère des protocoles d'interface et optimise le partage des ressources. Par exemple, la même fonction C peut se mapper à une interface AXI4-Stream, un esclave AXI4 maquillé en mémoire, ou les deux, simplement en changeant de pragmes.
Choisir le bon outil HLS
Plusieurs outils HLS matures sont disponibles, chacun étroitement intégré avec un écosystème de fournisseurs ou offert par des entreprises tiers EDA. La sélection dépend souvent de la famille de dispositifs cibles et de la complexité de la conception.
- AMD Vitis HLS (anciennement Vivado HLS): Le fleuron pour les appareils AMD Xilinx, supportant la synthèse du noyau C, C++ et OpenCL. Il génère RTL qui se branche directement dans l'intégrateur IP Vivado et fonctionne en toute transparence avec la plate-forme logicielle unifiée Vitis pour les applications accélérées. Plus de détails sont disponibles sur la page de produit AMD Vitis HLS.
- Compilateur de synthèse de haut niveau Intel (HLS Compiler): Intégré dans Intel Quartus Prime, cet outil synthétise C++ pour les FPGA Intel Agilex, Stratix et Arria. Il excelle dans les conceptions à forte intensité de données et prend en charge le parallélisme des tâches et la pipeline en boucle fine. Les matériaux de référence sont sur la page ].
- Siemens Catapult HLS: Outil d'agnostic fournisseur qui synthétise à partir de SystemC ou C++ pour les cibles ASIC et FPGA. Il est largement utilisé dans les applications aérospatiales et automobiles et offre un contrôle d'équivalence formel, ce qui le rend adapté pour les systèmes critiques pour la sécurité.
- Open-Source Options:[ L'outil Bambu HLS[ de Politecnico di Milano est un cadre open-source activement maintenu qui accepte la norme C et génère Verilog. Bien que non aussi axé sur les performances que les outils de fournisseurs, il est excellent pour l'enseignement et la recherche, et il soutient l'exploration flexible des algorithmes HLS.
Chaque outil a sa propre philosophie de syntaxe et d'optimisation pragma, mais les concepts HLS de base restent cohérents. Les exemples de cet article se concentrent sur les outils fournis par les fournisseurs mais s'appliquent largement à toutes les plateformes.
Le flux de conception basé sur le HLS
L'adoption de HLS signifie passer d'un flux de travail axé sur RTL à un cycle de codage, de simulation et de raffinement progressif, comme un logiciel. Les étapes suivantes décrivent un flux complet de l'algorithme à bitstream.
Étape 1: Spécification de l'algorithme et validation du niveau C
Comme la synthèse HLS est sensible au style de codage, séparer la fonctionnalité synthésisable du code de harnais de test non synthésisable, généralement en plaçant l'algorithme de base dans une fonction dédiée. Éviter l'attribution dynamique de la mémoire, la récursion et les appels système à l'intérieur du code synthésisable. Utiliser des tableaux de taille fixe, des types de données à point fixe, le cas échéant, et compiler des limites de boucles. Porter une attention particulière aux types de données : utiliser , ou de la bibliothèque HLS plutôt que ou , à moins que le point flottant n'impose des coûts de ressources lourdes.
Valider le modèle doré avec la compilation et la simulation standard C (p. ex., en utilisant GCC ou MSVC). Ceci capture les erreurs algorithmiques tôt, bien avant que la simulation matérielle commence. L'outil HLS utilisera plus tard le même testbench pour la co-simulation C/RTL, donc investir l'effort ici paie très bien.
Étape 2: Configuration de l'outil et spécification de la cible
Créez un nouveau projet HLS dans votre outil choisi (Vitis HLS, Intel HLS Compiler, etc.). Vous devez définir :
- La fonction supérieure à synthétiser.
- La partie ou la carte FPGA cible, qui détermine les ressources disponibles, la fréquence des horloges et l'architecture des appareils.
- La contrainte de la période d'horloge, généralement en nanosecondes. Cela entraîne des décisions de programmation et de pipeline.
- Paramètres de simulation et, pour Vitis HLS, si vous devez utiliser la simulation ou la co-simulation C avec un simulateur RTL externe.
Une erreur courante est de fixer une période d'horloge trop optimiste, causant des défaillances de synthèse plus tard. Commencez par une cible conservatrice (p. ex., 10 ns / 100 MHz) et serrez graduellement après avoir examiné les rapports de programmation.
Étape 3: Optimisation du code par l'utilisation de pragmas et de directives
Les pragmas sont le principal mécanisme de guidage de l'outil HLS. Sans eux, l'outil synthétise un design sûr mais sous-optimisé – boucles séquentielles, ressources entièrement partagées, parallélisme minimal. Les directives clés d'optimisation comprennent:
- La canalisation en boucle:[ provoque un chevauchement des itérations de boucles, initiant une nouvelle itération tous les cycles II (intervalle d'initiation). Un pipeline II=1 produit un résultat par cycle d'horloge après la latence initiale, maximisant le débit.
- Loop dérolling:[ réplique des corps de boucle pour exécuter plusieurs itérations en parallèle, échange de zone pour la performance.
- Arrayer la partition et le remodelage:[ divise les tableaux en petites banques de mémoire pour un accès parallèle. combine les données divisées en un mot mémoire unique plus large.
- Fonction inline:[ fusionne les hiérarchies de fonctions, donnant à l'outil plus de marge pour l'optimisation transfrontalière.
- Pragmas d'interface:[ Spécifiez comment la fonction supérieure se connecte— pour la diffusion, pour une interface de contrôle macisée en mémoire, pour l'accès externe à la mémoire DDR, etc.
- Dataflow: permet un parallélisme au niveau des tâches, permettant à une séquence de fonctions ou de boucles de fonctionner simultanément en tant que pipeline avec des canaux de streaming.
- Les directives ou peuvent limiter le nombre de DSP ou de ports de mémoire, empêchant ainsi la contestation des ressources.
Bien choisi pragmas peut signifier la différence entre un design qui rencontre à peine le débit et qui laisse les ressources inactif. Le processus d'optimisation est itératif: appliquer des directives, synthétiser, inspecter les rapports de performance et d'utilisation, et affiner. Gardez un journal de qui pragmas ont été essayés et leur effet sur la zone et la latence.
Étape 4: Synthèse et analyse
Exécutez la synthèse HLS pour produire le code RTL et des rapports complets. Le rapport le plus important est le profil de performance, montrant chaque latence de boucle, l'intervalle d'initiation et la profondeur du pipeline. Le rapport d'utilisation des ressources décompose les LUT, les tongs, les DSP et les blocs d'utilisation de RAM.
Si l'intervalle d'initiation ou la latence atteint un niveau supérieur à celui souhaité, recherchez des dépendances -portées par -loop ou des conflits de port de mémoire marqués dans le rapport. Souvent, une construction subtile – comme un accumulateur dépendant de sa valeur précédente – prévient l'atteinte de II=1 sans recodage ou partitionnement de tableau. Utilisez le visionneur de calendrier pour identifier les décrochages.
Étape 5 : Cosimulation C/RTL
Avant d'intégrer le RTL généré dans un modèle FPGA plus grand, vérifiez l'équivalence fonctionnelle par la co-simulation. L'outil compile le testbench C original contre le RTL généré à l'aide d'un simulateur groupé (par exemple Xcelum, ModelSim ou Vivado Simulator). Il passe les mêmes vecteurs d'entrée et compare le cycle de sortie par cycle. La co-simulation non seulement confirme la justesse logique mais expose également les erreurs de synchronisation, comme lorsque le modèle C suppose des écritures de mémoire immédiates pendant que le RTL a écrit des retards dus à la latence BRAM.
Si des erreurs se produisent, inspecter la forme d'onde ou le journal des transactions. Ajuster le modèle ou le pragmas C (p. ex. ajouter avec latence appropriée) jusqu'à ce que le comportement RTL corresponde au cycle du modèle doré. Il est bon d'exécuter la co-simulation sur de petites sous-fonctions avant de passer à la conception complète, réduisant ainsi les itérations de débogue.
Étape 6: Exporter la PI et intégrer le flux de conception FPGA
Une fois vérifié, exportez le design en tant que noyau IP emballé, habituellement en format IP-XACT ou Intel Qsys. Ce bloc IP peut ensuite être innové dans un bloc de conception (p. ex., Vivado IP Integrator) aux côtés d'autres modules RTL, processeurs souples ou contrôleurs de mémoire. L'IP généré par HLS comprend des contraintes de temps et est prêt pour le placement et le routage.
Dans le flux FPGA traditionnel, vous exécutez ensuite synthèse et implémentation (place-and-route) pour générer le flux bit final. Surveillez attentivement les rapports de calendrier de mise en œuvre. Les outils HLS fournissent un calendrier estimé basé sur des modèles pré-placement; le placement réel peut révéler des retards de routage plus longs, vous exigeant de détendre l'horloge cible ou de revoir les contraintes HLS. Si une boucle , cible II ne peut pas être atteinte dans le matériel, l'outil va réduire l'horloge ou la conception va échouer le calendrier, donc cette boucle de rétroaction est essentielle.
Exemple pratique : Mettre en œuvre un filtre FIR avec HLS
Pour solidifier ces concepts, envisagez un filtre à réponse par impulsion finie (FIR) – un bloc de construction de traitement de signal numérique commun. Le code C ci-dessous implémente un filtre FIR 16-tap avec des coefficients de points fixes.
#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);
}
Pragmas clés dans cet exemple:
- axe INTERFACE:[ Utilise AXI4-Stream pour l'entrée et la sortie, idéal pour le flux continu de données.
- ARRAY PARTITION complète:[ Sépare le registre de changement dans des registres individuels, permettant un accès parallèle à tous les robinets.
- PIPELINE II=1:[ S'assure qu'un nouvel échantillon est traité par cycle d'horloge après la latence initiale.
Après synthèse, vérifiez les rapports : la boucle de décalage devrait atteindre II=1, et l'utilisation des ressources (DSP pour les multiplications) devrait s'aligner avec 16 multiplicateurs. Cette conception est ensuite exportée comme un noyau IP et intégrée dans un système plus grand – par exemple, connecté à un DMA AXI pour diffuser des données d'un capteur. Cet exemple montre comment quelques pragmas traduisent une fonction C simple en un accélérateur matériel haute performance.
Stratégies d'optimisation des résultats et du domaine
L'efficacité du SDM exige un équilibre entre le débit, la latence et la consommation de ressources.
- Préférez l'arithmétique en points fixes:[ Les opérations en points flottants consomment des ressources importantes et une fréquence limite.À moins que l'étendue dynamique ne soit critique, utilisez des types de points fixes (p. ex. ] dans Vitis HLS) pour réduire les nombres de DSP et de LUT tout en préservant la précision.
- Stream datas au lieu de l'accès aléatoire à la mémoire: Le matériel est le plus efficace lorsque les données circulent à travers un pipeline. Utilisez ] ou des constructions de streaming similaires pour connecter les tâches, évitant les grands souvenirs partagés qui conduisent à l'arbitrage et les décrochages tampons.
- Nichons de boucles de structures pour des nids de boucles parfaits: L'outil peut pipelineer une boucle la plus intérieure automatiquement. Assurez-vous que les boucles n'ont pas de dépendances en boucle au-delà des modèles connus (p. ex., réduction).
- Utilisez la métaprogrammation de gabarit pour la configurabilité :[ Les modèles C++ permettent la paramétration à temps de compilation des tailles de tableau et des largeurs de données, rendant la même source HLS réutilisable sur les appareils sans perte de performance.
- Partage des ressources et latences de balance:[ La directive peut forcer le partage d'opérateurs coûteux comme les diviseurs. Cependant, le sur-partage peut sérialiser les opérations et augmenter la latence; peser contre la performance du pipeline.
- L'utilisation de représentations à points fixes bien typées réduit le coût du matériel. Par exemple, pour les données de pixel utilise des ressources minimales tout en conservant la précision nécessaire. Toujours l'erreur de quantification de profil contre la tolérance algorithmique.
Les outils HLS offrent également des répertoires -solution--où vous pouvez maintenir plusieurs ensembles d'optimisation (par exemple, -zone basse, - haut débit) et les comparer.
Débogue et vérification Pratiques exemplaires
Les conceptions de débogage HLS diffèrent des logiciels et du débogage RTL. Comme le code source est C++, les débogueurs traditionnels peuvent valider les fonctionnalités mais ne peuvent pas révéler le parallélisme matériel ou les bogues de synchronisation. Les pratiques suivantes réduisent la douleur :
- Maintenez un modèle C++ pur et approximatif qui utilise les mêmes protocoles d'interface (par exemple, streaming) pour pouvoir simuler rapidement.
- Mettre en place des bancs d'essai auto-vérifiés avec génération d'entrées randomisée et sorties de référence dorées.
- Utilisez l'outil HLS pour identifier les avertissements de log et de pragma de manière agressive. Traitez les constructions non-synthésiques ou les structures de boucles sous-optimales comme des erreurs.
- Commencer à co-simulation tôt sur un petit sous-module avant de passer à la conception complète.
- Utilisez l'outil HLS , analyse de performance intégrée pour voir les goulets d'étranglement de l'intervalle d'initiation avant de faire de longues simulations RTL.
- Inspecter le code RTL généré pour les structures inattendues : par exemple, les grands multiplexeurs indiquent souvent des branches conditionnelles trop complexes. Simplifier les conditions en aplatissant les énoncés imbriqués lorsque c'est possible.
Pièges courants et comment les éviter
Même les ingénieurs expérimentés rencontrent des problèmes répétés lors de leur déménagement vers HLS.
- Loops non-bounded: Les boucles avec des nombres de trajets variables qui ne sont pas calculables au moment de la compilation ne peuvent pas être correctement programmées.
- Les grandes interfaces mémoire avec une faible bande passante : Une interface maître AXI4-Lite unique pour les grands tableaux de données va bloquer les performances. Pour un haut débit, utilisez AXI4-Stream ou AXI4 master avec conversion de la largeur de données et support de rupture, commandé par des pragmas appropriés.
- Ignorer la réinitialisation et l'initialisation:[ Contrairement à la RTL pure, HLS suppose parfois que les registres peuvent démarrer dans un état valide. Assurez-vous d'avoir une stratégie propre de réinitialisation et évitez les tableaux locaux non initialisés qui peuvent déduire des RAM non initialisées (utilisez si nécessaire).
- Sur-reliant sur l'auto-optimisation de l'outil: Bien que les outils HLS soient puissants, ils ne peuvent pas deviner l'intention de conception. Un protocole simple poignée de main peut nécessiter une sélection explicite d'interface pour correspondre au comportement attendu; en s'appuyant sur des défauts peut conduire à des interfaces mal appariées.
- Ne pas appliquer de contraintes temporelles réelles : Le calendrier HLS utilise un modèle de chronométrage simple. L'emplacement physique de filets à haut risque ou de grands multiplexeurs peut causer des violations temporelles inattendues.
- Pour éviter de vérifier les décrochages de pipelines:[ Dans une boucle de pipelines, si le flux d'entrée s'arrête, le pipeline doit être capable de s'écouler sans blocage.
Intégration de HLS avec les systèmes hétérogéniques
Les plates-formes modernes FPGA associent logique programmable avec les systèmes de processeurs durs (par exemple ARM Cortex à Zynq, Agilex SoC). HLS s'intègre naturellement dans ces architectures. Un modèle commun est d'utiliser le processeur pour contrôler et configurer un accélérateur généré par HLS via AXI-Lite, tandis que les flux de données à haut débit via les ports-maîtres AXI4-Stream ou AXI4. La documentation Vitis HLS fournit des conseils détaillés sur l'intégration avec les API Xilinx Runtime (XRT) et OpenCL. De même, Intels HLS Compiler dans le cadre d'un API permet au même code noyau C++ de cibler les processeurs et les FPGA, simplifiant ainsi le développement d'accélérateurs reconfigurables.
Pour les systèmes de contrôle en temps réel, HLS peut générer un périphérique RTL personnalisé qui interagit avec le processeur , le traitement des E/S critiques en temps pendant que le processeur gère les politiques et les piles réseau. Cette division de travail maximise les performances sans sacrifier la flexibilité. Lors de la conception de tels systèmes, attention à la correspondance de la largeur des données: un maître AXI4 avec une interface 64-bit peut nécessiter une logique d'alignement de rupture dans le noyau HLS.
L'avenir de la synthèse de haut niveau
Le HLS évolue rapidement, avec des améliorations dans l'heuristique du compilateur, la vérification formelle et les écosystèmes de bibliothèque.
- Machine learning for AutoML-style HLS:[ Les outils commencent à intégrer des modèles ML qui prédisent des configurations pragma optimales, réduisant le réglage manuel. La recherche du milieu universitaire et de l'industrie vise à construire une synthèse --bouton---qui rivalise avec des conceptions expertes.
- Standardisation autour de C++17 et au-delà: Comme les front-ends HLS adoptent des standards C++ modernes, les concepteurs peuvent utiliser constexpr, lambdas et la métaprogrammation de gabarits pour écrire des bibliothèques matérielles hautement paramétrées et réutilisables.
- Une intégration plus étroite avec la vérification de haut niveau :[ La méthodologie de vérification universelle (UVM) et la modélisation de transaction de systèmeC sont combinées avec HLS pour créer des flux de conception et de vérification unifiés, réduisant ainsi le goulot d'étranglement de la vérification.
- Les piles matérielles open-source:[ Les projets comme CHIPS Alliance favorisent les cadres et bibliothèques HLS ouverts, rendant HLS plus accessibles au-delà des principaux fournisseurs FPGA.
- L'augmentation du support pour la reconfiguration dynamique :[ Les flux futurs de HLS peuvent permettre l'échange de noyaux pendant le temps d'exécution, permettant des systèmes adaptatifs qui se reconfigurent en réponse à des charges de travail changeantes.
Avec la croissance de la densité de FPGA, la gestion de la complexité au niveau RTL devient insoutenable. HLS offre un moyen de gérer cette complexité en augmentant le niveau d'abstraction tout en conservant l'efficacité matérielle.