Запуск DOOM на процессоре собственной разработки
Культовый шутер Doom, представленный студией id Software в 1993 году, навсегда изменил облик игровой индустрии. Сегодня игра стала мерилом технического прогресса: фраза «запустить Doom на чём угодно» давно стала девизом энтузиастов, которые переносят классику на самые неожиданные устройства — от бытовой техники до колоний бактерий.
Две недели назад мы совершили невозможное: запустили Doom на собственном процессоре, спроектированном «с нуля». Видео с этим достижением мгновенно стало виральным, собрав миллионы просмотров. Мы проделали огромный путь: от разработки архитектуры CPU на уровне логических вентилей и создания периферийных контроллеров до портирования исходного кода игры и реализации всего этого комплекса на базе FPGA в режиме реального времени. Ранее наша система справлялась лишь с примитивными задачами вроде Pong или фракталов Мандельброта, но теперь она способна запускать полноценные коммерческие игры, хотя реализация этого проекта оказалась крайне тернистой.
Амбициозные цели
Начав с конвейерной архитектуры, мы стремились к покорению новых высот. Однако, оставив позади 50-летние игры, мы столкнулись с жесткими ограничениями: нехваткой памяти и низкой производительностью. Вся доступная BRAM-память нашей FPGA составляла менее мегабайта, в то время как лишь один файл данных shareware-версии Doom (doom1.wad) весит 14 МБ. Кроме того, на нашей базовой архитектуре игра едва функционировала, превращаясь в бесконечное слайд-шоу.
Решение требовало разделения усилий. Лиам занялся внедрением механизмов исполнения с изменением последовательности (out-of-order execution) для повышения параллелизма, а я взял на себя задачу интеграции внешней памяти DDR3 — задачу обманчиво простую на бумаге, но сложную в реализации.
Работа с памятью
Изначально наш процессор полагался на внутреннюю BRAM с предсказуемой задержкой в один такт. Это позволяло избежать простоев конвейера. Внешняя DDR3-память работает по иным правилам: она медленнее, обладает переменной латентностью и широкой шиной данных. Чтобы не допустить падения производительности CPU до катастрофических значений, нам потребовалось внедрить систему кэширования. Грамотно реализованный кэш позволяет удерживать наиболее востребованные данные в быстрой BRAM, минимизируя обращения к «тяжелой» DDR3.
Архитектурные решения
Наш процессор построен по классической пятиступенчатой схеме: выборка (Fetch), декодирование (Decode), считывание регистров (Read), исполнение (Execute) и запись (Writeback). Каждая стадия абстрагирована через единый интерфейс.
Основные узлы конвейера
Стадия Fetch теперь опирается на кэш команд (ICache) и самостоятельно управляет задержками при перенаправлении потока выполнения. В условиях работы с DDR3 это стало сложнее, так как запросы к памяти могут быть отправлены до момента осознания необходимости перехода, что потребовало от нас механизмов отмены неактуальных операций.
Этап Decode выполняет трансформацию 32-битных инструкций в управляющие пакеты, понятные исполнительным блокам.
Блок Read претерпел серьезные изменения: чтение теперь также конвейеризировано. Для предотвращения конфликтов данных (RAW — Read-After-Write) мы внедрили Register Usage Map (RUM). Эта 32-битная карта состояния регистров позволяет процессору динамически решать, когда следует приостановить выполнение, что значительно надежнее прежних попыток предсказания состояний.
Стадия Execute управляет логикой вычислений, передавая команды в АЛУ или модули доступа к памяти. В случае ветвления конвейер очищается, а при работе с памятью процессор уходит в режим ожидания ответа от кэша.
Подсистема памяти
Поскольку процессор требует данные в каждом такте, а DDR3 выдает их порциями с высокой задержкой, мы разделили кэши на командный (ICache) и данных (DCache). Каждый из них имеет архитектуру прямого отображения с 2048 линиями. Метка (tag) гарантирует корректность данных, а сигналы валидности и модификации (dirty bit) обеспечивают целостность при записи.

Управление конфликтами
Для разрешения одновременных обращений двух кэшей к единственному контроллеру DDR3 был создан блок арбитража. Он выстраивает запросы в очередь и отдает приоритет DCache, что предотвращает взаимные блокировки системы.
Интеграция с реальным «железом»
Переход от симуляции к реальному FPGA потребовал использования IP-блока Xilinx MIG для работы с DDR3. Из-за проблем с таймингами и ограничениями текущей платы мы перешли на конфигурацию с 64-битной шиной. Стабильность работы между различными тактовыми доменами обеспечили FIFO-буферы и методы CDC (Clock Domain Crossing).
Периферия и ввод-вывод
Для взаимодействия с внешним миром мы реализовали MMIO. Контроллер VGA был расширен до поддержки 12-битной палитры и вывода через HDMI. UART-порт с FIFO-буфером взял на себя роль отладочного канала, а вместо USB-хоста, с которым возникли аппаратные сложности, мы организовали передачу нажатий клавиатуры через серийный интерфейс с ноутбука.
Портирование Doom
Адаптация игры проходила с помощью проекта doomgeneric. Процесс сопровождался борьбой с багами: от проблем с printf до нестабильности при обработке прерываний. Выяснилось, что ряд ошибок был вызван неверными предположениями игры об обнулении оперативной памяти при старте — пришлось внедрить принудительную инициализацию DDR3 в коде загрузчика.

Стартовая производительность составила всего 0,7 FPS, что заставило нас перейти к этапу глубокой оптимизации.
Путь к играбельной частоте кадров
Повышение тактовой частоты до 125 МГц дало незначительный прирост. Основные успехи пришли с оптимизацией конвейера (устранение дублирующих запросов ICache) и переходом на архитектуру RV32I-ZMMUL. Прямая запись данных в BRAM контроллера VGA и сокращение латентности кэша до одного такта подняли FPS до 6,7.
Финальным рывком стала компиляторная оптимизация (флаг O2). После устранения бага с пропущенным квалификатором volatile для MMIO-регистров таймера, игра наконец «взлетела», показав стабильные 15-20 FPS.
Заключение
Этот проект стал для нас настоящей школой инженерного мастерства. Мы прошли путь от примитивной логики до сложной системы с кэшированием, арбитражем памяти и оптимизацией ПО. Вирусный успех нашего видео лишь подтверждает: сообщество ценит смелые эксперименты. В планах — дальнейшее развитие архитектуры, внедрение полноценного out-of-order исполнения и, возможно, будущий портинг Quake 2 на более мощной аппаратной базе.
Издатель War Thunder привлек композитора Silent Hill к работе над extraction-шутером Active Matter
Remedy опубликовала системные требования Control Resonant для ПК
Bloober Team анонсировала необычный хоррор Onyx: The Dark Grip для Nintendo Switch 2
Bandai Namco самостоятельно убрала Denuvo из Code Vein II спустя семь месяцев после релиза
Компания MagicX может выпустить портативную консоль Pocket Dream в вертикальном форм-факторе Mini Dream
Инсайдер рассказал о планах Rockstar выпустить Red Dead Redemption 2 на Switch 2
EA Sports задействовала клонирование голоса для комментатора в NHL 27 при согласии самого диктора
Журналист назвал возможную причину задержки выхода Forza Horizon 6 на PS5