FPGA-процессор Hopper ускорил Doom с 0.7 до 15–20 кадров/с
Самодельный 32-битный RISC-V-процессор Hopper на FPGA запустил Doom со скоростью 15–20 кадров/с. Первая работавшая на реальном железе версия выдавала около 0.7 кадра/с, поэтому разработчикам пришлось последовательно переделать выборку инструкций, кэши, видеотракт, набор команд и сам порт игры. Исходники ядра на Chisel/Scala и адаптация doomgeneric опубликованы в репозиториях MIT-OpenCompute.
Hopper построен вокруг пятиступенчатого конвейера Instruction Fetch, Decode, Register Read, Execute и Writeback. Код и данные размещены во внешней DDR3, доступ к которой занимает, по измерениям команды, примерно 30–100 тактов. Перед памятью установлены раздельные ICache и DCache прямого отображения: по 2048 строк, каждая содержит четыре 32-битных слова. Это соответствует 32 КиБ на кэш. Попадание первоначально обслуживалось за два такта.
Первый заметный прирост появился после повышения частоты ядра со 100 до 125 МГц и исправления логики ICache, отправлявшей лишние запросы. Doom достиг примерно 2.5 кадра/с. Затем в ALU добавили умножение из расширения Zmmul, после чего скорость выросла до 3.5 кадра/с. Аппаратные деление и вычисление остатка оставили за пределами реализации: их включение потребовало бы дополнительных изменений конвейера и управления длительными операциями.
Следующим узким местом оказался вывод изображения. Кадры начали записываться прямо в BRAM видеоконтроллера, сократив трафик через DDR3. Одновременно обработку попаданий в кэш конвейеризировали и уменьшили задержку с двух тактов до одного. Эти изменения подняли результат примерно до 6.7 кадра/с.
Последний крупный скачок обеспечила сборка Doom с `-O2` вместо `-O0`. До этого оптимизация ломала чтение MMIO-таймера: регистр не был объявлен `volatile`, и компилятор мог удалить повторные обращения к периферии. После исправления порт достиг заявленных 15–20 кадров/с. В систему также входят UART, аппаратный таймер, видеовыход и клавиатурный интерфейс. Из-за проблем с питанием USB-клавиатуры на плате события клавиш во время отладки передавались с ноутбука по UART.
Получившийся прирост показывает распределение потерь в небольшой FPGA-системе. Увеличение тактовой частоты дало лишь часть результата; сопоставимый эффект принесли локальность видеобуфера, однократное попадание в кэш и корректная оптимизация кода. Следующей целью названы 30 кадров/с, внеочередное исполнение и дальнейшая переработка подсистемы памяти. Текущие 15–20 кадров/с остаются измерением авторов проекта: стандартизированный сценарий, покадровый лог и независимое воспроизведение пока не опубликованы.