Аудит ieee.float_pkg для VHDL: 1 271 619 из 8 692 326 вызовов в 7-битном формате округлены неверно
Сверка с точной арифметикой выявила ошибки округления и остановки симулятора в пакете IEEE, который GHDL и NVC поставляют без изменений; авторы опубликовали патч.

Авторы аудита, опубликованного на github.com, сообщают, что ieee.float_pkg, пакет чисел с плавающей запятой стандарта VHDL IEEE Std 1076-2008 и 1076-2019, возвращает результаты, округлённые неверно. Файл публикует IEEE, а GHDL и NVC поставляют его без изменений. Для всех операндов и пар в 7-битном формате (3 бита порядка, 3 бита дроби), а также всех троек для умножения с накоплением авторы выполнили 8 692 326 вызовов, и 1 271 619 из них округлены неверно github.com
github.comgithub.comОткрыть источник ↗.
Простейший случай — квадратный корень: sqrt(2,0) в двойной точности по умолчанию возвращает значение на одну единицу последнего разряда ниже верного. Оно отстоит от корня на 0,565 единицы, тогда как правильно округлённое значение — на 0,435. Умножение с накоплением (-6)(-1)+(-5) возвращает -15 вместо 1; преобразование 2^-512 из двойной точности в одинарную возвращает 1,0; обратная величина 2^127 в одинарной точности возвращает бесконечность.
Как выполнена проверка
Проверка считает операнды точными дробями, выполняет каждую операцию точно и округляет один раз перед сравнением. Запуски выполнены в GHDL 7.0.0-dev и NVC 1.23.1, и на одних и тех же векторах оба записали одинаковые файлы результатов. На каждую операцию, формат и стиль округления пришлось по 10 000 вызовов на операндах, подобранных под места, где арифметика ломается: денормализованные числа, оба края диапазона порядка, точные середины, знаковые нули, бесконечности.
В float32 это дало 81 068 неверных результатов и 272 остановки симулятора в 859 771 вызове; в float64 — 86 081 неверный и 445 остановок в 857 234 github.com
github.comgithub.comОткрыть источник ↗. Затронуты и обычные операнды: из целых от 1 до 4 096 sqrt даёт расхождение на единицу для 256 в float32 и для 264 в float64. Минимальный тестовый файл содержит 25 вызовов: 24 печатают WRONG, а 25-й останавливает симулятор с выходом индекса за границы в строке 358 тела пакета.
Причины и патч
Авторы связывают ошибки с конкретными строками файла IEEE. В normalize (строка 422) порядок обрезается до ширины на два бита больше целевого формата, поэтому при переходе из float64 в float32 берётся по модулю 1 024. В divide (строка 1243) и reciprocal (строка 1099) «липкий» бит, передаваемый в округление, — константа '1', из-за чего точные середины уходят к неверному соседу. В reciprocal порядок результата не помещается в старшем двоичном интервале, и в float32 любой аргумент от 2^127 и выше даёт бесконечность. Квадратный корень использует фиксированное число шагов Ньютона и не имеет «липкого» бита.
В репозитории лежат точный эталон, тестовое окружение, причины с номерами строк и патч. С патчем проходят все 32 470 838 вызовов из четырёх наборов тестов. Авторы также сообщают, что деление в fixed_pkg даёт 41 026 неверных результатов из 751 418, и приводят патч и для него. О проблемах сообщено в рабочую группу IEEE P1076 (VHDL-Issues 388), ghdl 3486, nvc 1758 и fphdl 4.
Источники · 2
Нашли ошибку?Читайте также



