01signal.com

Guide pratique de la reconfiguration partielle avec Vivado

Introduction

Ceci est le deuxième article d’une série de quatre consacrée à la reconfiguration partielle (Partial Reconfiguration), aussi appelée Dynamic Function eXchange (DFX), avec Vivado de Xilinx. L’objectif de cet article est de parcourir et d’expliquer les étapes qui permettent d’activer la reconfiguration partielle sur un design FPGA. Il est recommandé d’avoir lu le premier article si ce n’est pas déjà fait, car il explique les concepts qui se cachent derrière ces étapes.

En 2020, Xilinx a rebaptisé la reconfiguration partielle « Dynamic Function eXchange » (DFX). C’est cette expression qui apparaît dans les menus et les notes d’information de Vivado. Le terme technique « reconfiguration partielle » est néanmoins employé ici.

Par souci de simplicité, cet article suppose qu’il n’y a qu’une seule partition reconfigurable dans le projet. Étendre cela à plusieurs partitions est relativement simple.

La procédure décrite dans cet article commence avant que le projet ne soit configuré pour la reconfiguration partielle. Pour résumer grossièrement, les étapes sont :

Préparation du floorplanning

Le floorplanning est, plus que toute autre tâche, celle qui demande de la réflexion. Il s’agit d’un équilibre subtil entre ne pas gaspiller la surface de logique du FPGA et faire en sorte que la partition statique comme les partitions reconfigurables ne rencontrent pas d’obstacles majeurs pendant le placement et le routage (place and route).

C’est pourquoi la majeure partie de cet article est consacrée à ce sujet.

À une époque lointaine, le floorplanning était utilisé pour obtenir la convergence temporelle (timing closure). Il aidait les outils à placer la logique de façon cohérente. Les outils de conception FPGA s’étant améliorés avec le temps, cela fait de nombreuses années que je n’ai pas vu le floorplanning aider à respecter les contraintes de timing (timing constraints). Aujourd’hui, la meilleure stratégie pour atteindre les contraintes de timing est presque toujours de laisser les outils décider.

Avec la reconfiguration partielle, le floorplanning est obligatoire ; l’objectif est donc de ne pas empirer les choses. En général, on procède par essais et erreurs. La méthode la plus simple pour obtenir de bons résultats consiste toutefois à réaliser une implémentation du design sans floorplanning, puis à partir de la façon dont la logique se place naturellement. L’étape suivante consiste à organiser les zones d’une manière qui ait du sens pour la reconfiguration partielle, en utilisant le placement initial de la logique comme fil conducteur.

Dans le scénario d’usage plugin, le floorplanning peut être mis à jour au fil de l’évolution du projet. Ce n’est en revanche pas le cas dans le scénario Remote Update, c’est-à-dire lorsque la reconfiguration partielle sert à publier des mises à jour de version d’un design déjà diffusé : avec Remote Update, tous les flux partiels doivent correspondre au flux initial. En conséquence, la partie de logique statique du design est figée dès la diffusion du flux initial. Cela signifie, entre autres, que le floorplanning doit rester identique.

Ainsi, avant même de se lancer dans la reconfiguration partielle, la première tâche consiste à trouver une zone appropriée dans le FPGA pour la logique statique. Inutile d’y consacrer trop de temps : il s’agit simplement d’obtenir un point de départ pour la suite, une fois le projet scindé en deux morceaux.

Ne vous y trompez pas : le but de cette première étape n’est pas le floorplanning en soi, mais de voir comment Vivado place la logique sans contraintes, et d’en déduire quelle zone doit être allouée à la logique statique. Voici les étapes :

Configuration d’un projet pour la reconfiguration partielle

La UG909 de Xilinx suggère deux procédures de travail pour la reconfiguration partielle :

Je vais utiliser ici le flux par projet, même s’il comporte quelques limitations, dont certaines concernent le type de sources du module reconfigurable (notamment pour ce qui est des block designs). Quoi qu’il en soit, mieux vaut commencer par le flux par projet, car les scripts d’implémentation qu’il génère constituent une bonne base pour le flux sans projet, si le besoin s’en fait sentir.

Voici les étapes pour activer la prise en charge de la reconfiguration partielle dans un projet existant :

Si vous tentez d’implémenter le projet à ce stade, vous obtiendrez très probablement une erreur du genre « [DRC HDPR-30] Missing PBLOCK On Reconfigurable Cell: HD.RECONFIGURABLE cell 'pr_block_ins' must have PBLOCK assigned to itself or its descendant cells ». Autrement dit, le floorplanning est nécessaire.

Floorplanning.

À ce stade, le projet est configuré suffisamment pour pouvoir effectuer le floorplanning.

Avant de décomposer cette tâche en petites étapes, quelques points méritent d’être mentionnés :

Passons maintenant aux étapes :

Corriger le floorplanning

C’est sans doute la partie la moins agréable de la reconfiguration partielle : obtenir un floorplanning vraiment correct. Si vous travaillez pour le cas d’usage Remote Update, cette phase est encore plus importante, car ce floorplanning restera pendant toute la vie du projet.

Les corrections du floorplanning sont nécessaires pour deux raisons principales : répondre aux avertissements critiques, puis, à un stade ultérieur, optimiser l’utilisation du FPGA. L’objectif est de réduire le gaspillage de ressources tout en évitant de créer des obstacles pour le placement et le routage.

Faire des modifications n’est pas difficile : il suffit de déplacer les limites d’un Pblock à la souris. On peut aussi élargir un Pblock avec des rectangles supplémentaires : faites un clic droit sur le Pblock et sélectionnez « Add Pblock Rectangle ».

Les avertissements critiques indiquent souvent les corrections nécessaires ; il faut néanmoins avoir lu le chapitre correspondant (6, 7 ou 8) du guide utilisateur de Xilinx, UG909, au sujet des limites du floorplanning pour votre FPGA particulier.

Le reste de cette section traite des problèmes possibles avec les FPGA de la série 7. Les FPGA Ultrascale sont beaucoup plus faciles à utiliser.

Une erreur courante avec les FPGA de la série 7 est la division des colonnes de tuiles d’interconnexion (interconnect tile columns). Par exemple :

[Constraints 18-993] The Pblock pblock_pr_block_ins has defined an area that causes the splitting of interconnect tile columns. Dynamic Function eXchange requires that the left and right paired interconnect tile columns cannot be split by a reconfigurable boundary.  This is caused by either the left or right edge of a Pblock boundary, or by the Pblock spanning over logic types not included in the Pblock ranges.  To avoid an unroutable situation, placement will be prohibited from both of these columns. To avoid placement restrictions, modify the Pblock to avoid splitting the two columns.
The column of the split contains interconnect tile INT_L_X48Y299  (SLICE_X79Y299 SLICE_X78Y299).
Please refer to the Xilinx document on Dynamic Function eXchange.
Resolution: Set the Pblock property SNAPPING_MODE to value of ON, or modify the column/X specification of the pblock to avoid this edge.

et

[Constraints 18-996] The split between the left and right columns occurs between a reconfigurable Pblock and Static logic. The static sites are not reconfigurable. The Pblock should be adjusted to remove the column from the Pblock, unless the excluded reconfigurable and static sites are not needed for the design. Note that adjusting the Pblock will prevent prohibits and improve placement of the design, but may reduce the routability if the removed sites were needed to span across the static logic. Failure to modify the Pblock may lead to an unplaceable design if these prohibited sites are required by the design. Resolution: Set the Pblock property SNAPPING_MODE to value of ON, or modify the column/X specification of the pblock to avoid this edge. and

Pour corriger cela, réglez la propriété SNAPPING_MODE du Pblock sur ROUTING ou ON (il y a de fortes chances que ROUTING ne suffise pas, alors choisissez ON), comme suggéré dans le premier avertissement. Cela ajoutera probablement beaucoup de contraintes au fichier XDC, du genre :

set_property PROHIBIT true [get_sites SLICE_X79Y349]
set_property PROHIBIT true [get_sites SLICE_X78Y349]
[ ... ]
set_property PROHIBIT true [get_sites SLICE_X79Y191]
set_property PROHIBIT true [get_sites SLICE_X78Y191]
set_property PROHIBIT true [get_sites PMV_X0Y2]
set_property PROHIBIT true [get_sites SLICE_X36Y190]
set_property PROHIBIT true [get_sites SLICE_X37Y190]
[ ... ]
set_property PROHIBIT true [get_sites SLICE_X79Y176]
set_property PROHIBIT true [get_sites SLICE_X78Y176]
set_property PROHIBIT true [get_sites T14]
set_property PROHIBIT true [get_sites R15]
set_property PROHIBIT true [get_sites XADC_X0Y0]
set_property PROHIBIT true [get_sites SLICE_X36Y175]
set_property PROHIBIT true [get_sites SLICE_X37Y175]
[ ... ]

et ainsi de suite.

Les contraintes PROHIBIT posées sur les sites de type slice sont celles qui font taire l’avertissement critique en question. Les autres affectations PROHIBIT sont ajoutées pour des sites logiques inclus dans la zone géométrique, mais qui ne sont pas autorisés pour la reconfiguration partielle sur le FPGA utilisé. Les FPGA Ultrascale et plus récents produisent nettement moins de lignes PROHIBIT, voire aucune.

Si le but est uniquement de faire taire l’avertissement critique, il est probablement acceptable de supprimer toutes les lignes PROHIBIT et de n’en conserver qu’une seule, uniquement pour les slices. Pour cela, couvrez la plage de slices que Vivado a ajoutée en réponse au changement de SNAPPING_MODE. Transformez donc cette plage en quelque chose comme :

set_property PROHIBIT true [get_sites -range {SLICE_X79Y0 SLICE_X79Y349}]

C’est le genre de ligne dans le fichier XDC qui peut résoudre le problème de division des colonnes d’interconnexion sans rendre le fichier énorme.

Quoi qu’il en soit, une ligne de ce type peut aussi apparaître dans le fichier XDC. La supprimer ne pose apparemment aucun problème :

set_property HD.PLATFORM_WRAPPER true [get_cells pr_block_ins]

Réduire le fichier XDC au minimum qui fait taire les avertissements critiques peut sembler un peu superficiel, mais l’alternative est un fichier de contraintes énorme, source de confusion par la suite. D’après mon expérience, l’absence d’avertissements de ce genre peut être considérée comme une validation du floorplan du design.

Il y a de fortes chances que le fait de remettre la propriété SNAPPING_MODE à OFF pose à nouveau des problèmes, quelles que soient les modifications apportées au XDC.

Ajout d’un module reconfigurable

Jusqu’ici, l’implémentation revient pratiquement à une conception hiérarchique, avec quelques restrictions supplémentaires. Même si un flux binaire partiel est généré, il est assez inutile, car le charger ne change rien au design.

Le but est donc de créer un autre flux binaire partiel, basé sur un autre module reconfigurable. Cela nécessite d’ajouter une implémentation enfant (Child Implementation).

Ayez bien en tête le premier article avant de poursuivre, en particulier la partie sur les implémentations parente et enfant, ainsi que sur l’assistant Dynamic Function eXchange. Rappelez-vous aussi, comme indiqué plus haut dans cet article, que l’onglet « Partition Definitions » contient les modules reconfigurables actuellement définis et leurs sources.

Ouvrez l’assistant Dynamic Function eXchange depuis le menu Tools et cliquez sur Next dans la fenêtre d’accueil.

Dans la fenêtre Edit Reconfigurable Modules, cliquez sur « + ». Une boîte de dialogue s’ouvre pour ajouter un module reconfigurable. La seule chose réellement intéressante dans cette boîte de dialogue est le nom du module reconfigurable (Reconfigurable Module Name) : c’est le nom qui sert à identifier la logique reconfigurable, comme expliqué plus haut.

La boîte de dialogue demande aussi d’associer ce module à une définition de partition ; de toute façon, il n’y en a qu’une (car cet article suppose qu’une seule partition est définie).

Au moins un fichier source Verilog / VHDL doit être ajouté pour continuer ; d’autres pourront être ajoutés plus tard depuis l’onglet « Partition Definitions ». Indiquer le nom du module de plus haut niveau de ce module reconfigurable ne fait pas de mal, surtout s’il n’est pas évident à partir des fichiers sources eux-mêmes.

Revenez à l’assistant et cliquez de nouveau sur Next pour arriver à la fenêtre Edit Configurations. Cliquez sur « + » et saisissez un nom de configuration. Ce nom ne sert qu’à apparaître dans la fenêtre Design Runs. Un nom comme config_2 convient parfaitement.

Une nouvelle ligne apparaît dans la liste des configurations. Modifiez le module reconfigurable dans la colonne correspondant à la partition, afin que chaque configuration ait un module reconfigurable différent.

La dernière fenêtre est Edit Configuration Runs, qui sert à affecter des runs aux configurations. Le plus simple est de supprimer tous les runs listés dans cette fenêtre (s’il y en a), puis de cliquer sur « Automatically create configuration runs ». Cela fait ce que vous feriez de toute façon à la main : créer un run parent, l’appeler « impl_1 », puis créer des runs enfant, les appeler comme vous voulez, et en faire les enfants de « impl_1 ».

L’assistant choisit une configuration pour chaque run, mais cela se change facilement. La seule chose importante est de savoir quelle configuration est associée au run parent.

Au fait, si vous supprimez tous les runs dans l’assistant, tous les runs enfant disparaissent, mais impl_1 reste.

Enfin : l’implémentation du design

Pour générer les flux binaires, cliquez simplement sur « Generate Bitstreams » dans Vivado, comme d’habitude. Comme déjà mentionné dans le premier article, deux ou trois flux binaires sont créés pour chaque configuration dans un projet de reconfiguration partielle.

Par exemple, sur un FPGA Ultrascale, les fichiers .bit peuvent être :

Notez que le même nombre de fichiers de flux binaire est créé pour toutes les implémentations. Autrement dit, le fichier de flux initial est aussi créé pour les implémentations enfant ; il est donc tout à fait possible de charger le FPGA avec le flux initial de l’une des implémentations enfant et de continuer à partir de là.

Pour un moyen simple de charger des flux partiels par PCIe ou USB 3.x, voir cette page.

Aucune des implémentations ne devrait présenter d’avertissements critiques ni échouer à cause de plaintes concernant le Pblock ou le floorplanning en général, puisque ces problèmes devraient déjà être résolus. Si un tel problème survenait malgré tout, il faudrait corriger le floorplanning comme expliqué plus haut.

Il arrive parfois que, lorsqu’on clique sur « Generate Bitstream » alors que seules les implémentations enfant ont été modifiées, Vivado réponde « Bitstream generation has already completed and is up-to-date. Re-run anyway? ». C’est un peu déroutant, mais cliquer sur « Yes » lancera les implémentations enfant correctement. Cette histoire d’implémentation enfant est un peu un ajout à Vivado, ce qui explique aussi pourquoi la ligne d’état pendant l’implémentation affiche par exemple « write_bitstream complete. Child running ».

Examen des résultats

Comme la reconfiguration partielle tourne beaucoup autour du placement, il est bon d’examiner les designs implémentés. Vous pouvez ouvrir une implémentation particulière en faisant un clic droit sur « Open Implemented Design », puis en survolant l’élément de menu qui affiche à nouveau « Open Implemented Design ». Sélectionnez ensuite dans la liste l’implémentation à ouvrir. Si une implémentation manque dans la liste, c’est qu’elle est probablement déjà ouverte.

Essayez de faire un clic droit sur la ligne du niveau supérieur de la logique reconfigurable dans le panneau Netlist de la vue du design implémenté, puis choisissez « Highlight Leaf cells ». Faites de même avec la logique statique, dans une autre couleur.

Dans ce même menu contextuel, il y a aussi « Show Connectivity », qui trace des lignes blanches droites entre les éléments logiques connectés. Les chemins de routage (routing paths) réels sur le FPGA sont évidemment différents, de sorte que les zones de floorplanning traversées par ces lignes n’ont aucune signification. L’observation de la connectivité peut néanmoins aider à repérer les cas où l’organisation générale d’un floorplan fait peiner les outils.

Il est tout à fait normal que certaines cellules qui semblent appartenir à la logique statique soient placées dans la zone reconfigurable, et inversement. Ce qui doit attirer l’attention, c’est une éventuelle congestion — si la logique semble trop serrée en général, ou dans une région particulière. Si possible, des modifications du floorplanning peuvent aider à atténuer ce problème.

Autre chose à examiner : la position des broches de partition (partition pins). Elles apparaissent sous forme de barres horizontales blanches dans la vue du circuit, comme sur l’image suivante (cliquez sur l’image pour l’agrandir) :

Partition pins in Vivado's device view

Comme indiqué dans le premier article, les broches de partition peuvent se trouver n’importe où dans la partition reconfigurable. En revanche, si elles sont éloignées des bords de la partition, cela peut indiquer que le routeur a eu du mal avec le timing pendant l’implémentation parente.

On peut aussi obtenir une liste textuelle des coordonnées des broches de partition avec cette commande Tcl (remplacez pr_block_ins par le nom de la cellule de logique reconfigurable) :

foreach s [get_pins -of [get_cells pr_block_ins]] { set partpin [get_pplocs -quiet -pins [get_pins $s]] ; puts "$s => $partpin"; }

Les coordonnées des broches de partition correspondent à la grille des CLB (et non des slices). Sur le dessin affiché, ces broches sont appelées « Cell pins ».

Certaines broches de la cellule peuvent ne pas avoir de broche de partition associée. Cela se produit lorsqu’il y a une inadéquation entre la liste des ports du module reconfigurable (et/ou la largeur des vecteurs) et son instanciation (instantiation) par le module de logique statique. Une telle inadéquation est parfaitement légale (en Verilog), mais le résultat peut être indésirable. Cette commande Tcl permet de détecter les ports inaccessibles, en particulier lorsque cela est involontaire.


Ceci termine la partie technique sur la configuration du projet Vivado. Le prochain article aborde toutefois un aspect important de la conception FPGA : comment garantir que le remplacement de la logique se déroule de manière fiable et sans à-coups.

Cette page a été traduite de l’anglais par une machine. En cas de doute, veuillez vous reporter au texte original
Copyright © 2021-2026. All rights reserved. (dcc38493)