Contexte du package float_pkg
Le package ieee.float_pkg fait partie du standard VHDL IEEE 1076‑2008 et 1076‑2019. Il implémente les opérations flottantes (addition, multiplication, division, racine carrée, conversion, etc.) en manipulant des fractions exactes avant d’appliquer un unique arrondi selon le mode demandé. Le code source officiel, publié par l’IEEE, compte 5 712 lignes et est distribué tel quel avec les simulateurs GHDL 7.0.0‑dev et NVC 1.23.1.
Erreurs de précision observées
Une série de tests automatisés a comparé les résultats du package avec une référence exacte (exact.py). Sur 10 000 appels par opération, format et mode d’arrondi, plusieurs fonctions affichent des écarts d’une unité dans le dernier bit (ULP). Par exemple, sqrt(2.0) en double précision renvoie 3FF6A09E667F3BCC au lieu du 3FF6A09E667F3BCD attendu, soit un ULP trop bas. D’autres cas notables :
mac(-6.0, -1.0, -5.0) → -15.0 (devrait être 1.0)
resize(2.0**-512, 8, 23) → 1.0 (devrait être 0.0)
reciprocal(2.0**127) → +infinity (devrait être 2.0**-127)Les tableaux de comptage montrent que, pour le format float32, sqrt échoue dans 735 cas sur 10 000, multiply dans 1 102 cas, et mac dans 2 671 cas. Les erreurs augmentent fortement avec les modes d’arrondi round_zero, round_neginf et round_inf.
Analyse des causes techniques
Le cœur du problème réside dans l’algorithme de racine carrée et, plus généralement, dans les opérations de division. Le package utilise un nombre fixe d’étapes de Newton‑Raphson et ne conserve aucun sticky bit. Cette approche simplifie l’implémentation mais empêche le suivi de l’erreur résiduelle lors du dernier arrondi, ce qui conduit à un arrondi trop bas dans de nombreux cas. De plus, la conversion entre formats (par ex. de double à simple) ne gère pas correctement les sous‑normaux ; la conversion de 2^-512 en simple donne 1.0 au lieu de 0.0, et les puissances de deux très petites provoquent même l’arrêt du simulateur (index out of bounds).
Les tests couvrent également les fonctions de conversion to_signed et to_unsigned, où les arrondis sont parfois inversés (0 au lieu de 1, 199 au lieu de 200). Ces incohérences proviennent du même manque de suivi de la partie fractionnaire lors du dernier arrondi.
Implications et correctifs
Pour les concepteurs de circuits numériques qui s’appuient sur ieee.float_pkg pour la simulation, ces écarts peuvent entraîner des dépassements de spécifications, notamment dans les algorithmes de filtrage ou de contrôle où la précision de sqrt et de la multiplication est critique. Le dépôt GitHub fourni propose un patch qui corrige les 32 470 838 appels erronés en ajoutant un suivi de bit collant et en augmentant le nombre d’itérations de Newton. Après application du correctif, GHDL et NVC produisent des résultats identiques et conformes à la référence.
Le problème a été signalé au groupe de travail IEEE P1076 (VHDL‑Issues 388) sous les tickets ghdl 3486 et nvc 1758. En attendant l’adoption officielle, les utilisateurs sont encouragés à appliquer le patch localement ou à recourir à des packages alternatifs pour les calculs critiques.
ghdl -a --std=08 plain.vhd
ghdl --elab-run --std=08 plain