Разблокировка производительности FPGA с помощью синтеза высокого уровня

Полевые программируемые воротные массивы (FPGA) традиционно требовали глубокого опыта в языках описания аппаратного обеспечения (HDL), таких как VHDL и Verilog. Синтез высокого уровня (HLS) переворачивает эту модель, позволяя разработчикам писать алгоритмы на C, C++ или SystemC и автоматически генерировать оптимизированный код RTL. Этот сдвиг делает разработку FPGA доступной для инженеров-программистов при сокращении циклов итерации от концепции до рабочего оборудования. Освоение инструментов HLS может обеспечить повышение производительности 10 × или более, с производительностью и использованием ресурсов, которые часто конкурируют с ручным кодированием HDL. Это руководство охватывает основные методы, чтобы заставить HLS работать для вашего следующего проекта FPGA, включая подробный переход к реальному примеру.

Что такое синтез высокого уровня?

Синтез высокого уровня представляет собой процесс компиляции, который преобразует несвоевременное поведенческое описание — обычно в C/C++ — в реализацию синхронизированного оборудования. В отличие от компиляторов программного обеспечения, которые нацелены на фиксированный набор инструкций, HLS должен планировать операции в тактовые циклы, выделять функциональные блоки, связывать операции с конкретными аппаратными ресурсами и генерировать машину с конечным состоянием с паттерном данных. Этот процесс учитывает логические блоки FPGA, срезы DSP и архитектуру памяти, руководствуясь ограничениями времени и директивами оптимизации, установленными пользователем.

Критическим преимуществом является абстракция: циклы, массивы и вызовы функций синтезируются непосредственно без ручного создания машин состояний или трубопроводов для передачи данных. Инструмент выводит параллелизм, генерирует протоколы интерфейса и оптимизирует совместное использование ресурсов. Например, одна и та же функция C может отображаться в интерфейс AXI4-Stream, в рабе AXI4 с картой памяти или и то, и другое, просто изменяя прагмы. Это делает HLS особенно ценным для обработки видео, вывода машинного обучения, обработки цифровых сигналов и обработки сетевых пакетов, где уточнение алгоритма быстрое и производительность оборудования не подлежит обсуждению. Повышая уровень абстракции, HLS позволяет более тщательное исследование пространства проектирования на ранней стадии цикла разработки, снижая риск поздней стадии переделки.

Выбираем правильный инструмент HLS

Доступно несколько зрелых инструментов HLS, каждый из которых тесно интегрирован с экосистемой поставщиков или предлагается сторонними компаниями EDA. Выбор часто зависит от семейства целевых устройств и сложности дизайна.

Каждый инструмент имеет свой собственный прагматический синтаксис и философию оптимизации, но основные концепции HLS остаются последовательными.Примеры в этой статье сосредоточены на предоставляемых поставщиками инструментах, но широко применяются на разных платформах.

HLS-Based Design Flow (англ.)русск.

Принятие HLS означает переход от RTL-центричного рабочего процесса к программно-подобному циклу кодирования, моделирования и инкрементной уточненности. Следующие шаги описывают полный поток от алгоритма к битовому потоку.

Шаг 1: Спецификация алгоритма и валидация уровня C

Начните с реализации вашего алгоритма полностью на C или C++ в качестве «золотой модели». Эта модель должна быть бит-точной и самопроверкой, с тестовыми векторами, которые охватывают все угловые случаи. Поскольку синтез HLS чувствителен к стилю кодирования, отделите синтезируемую функциональность от несинтезируемого тестового кода, обычно помещая основной алгоритм в выделенную функцию. Избегайте динамического распределения памяти, рекурсии и системных вызовов внутри синтезируемого кода. Используйте массивы с фиксированным размером, типы данных с фиксированной точкой, где это необходимо, и границы петли времени. Обратите особое внимание на типы данных: используйте , или из библиотеки HLS, а не или , если это абсолютно не необходимо, поскольку плавающая точка накладывает большие затраты на ресурсы.

Проверить золотую модель с помощью стандартной компиляции и моделирования C (например, с использованием GCC или MSVC). Это улавливает алгоритмические ошибки на ранней стадии, задолго до начала аппаратного моделирования. Инструмент HLS позже будет использовать ту же самую тест-систему для совместной симуляции C/RTL, поэтому инвестирование усилий здесь окупается красиво. Подумайте о добавлении рандомизированного тестирования для подчеркивания модели.

Шаг 2: Конфигурация инструмента и спецификация цели

Создайте новый проект HLS в выбранном вами инструменте (Vitis HLS, Intel HLS Compiler и т. д.).

  • Высшая функция синтеза.
  • Целевая часть или плата FPGA, которая определяет доступные ресурсы, тактовую частоту и архитектуру устройства.
  • Сроки часов ограничены, как правило, в наносекундах, что приводит к принятию решений о планировании и трубопроводном проектировании.
  • Настройки моделирования и, для Vitis HLS, использовать ли симуляцию C или симуляцию с внешним симулятором RTL.

Правильная конфигурация обеспечивает соответствие оптимизации инструмента физическим возможностям синхронизации. Распространенной ошибкой является установка чрезмерно оптимистичного периода времени, что приводит к сбоям синтеза позже. Начните с консервативной цели (например, 10 нс / 100 МГц) и постепенно затягивайте после просмотра отчетов о расписании.

Шаг 3: Оптимизация кода с использованием прагм и директив

Прагмы являются основным механизмом для управления инструментом HLS. Без них инструмент синтезирует безопасный, но недостаточно оптимизированный дизайн - последовательные циклы, полностью общие ресурсы, минимальный параллелизм. Ключевые директивы по оптимизации включают:

  • Петлевое трубопроводирование: вызывает перекрытие итераций петлей, инициируя новую итерацию каждые II (интервал инициации) циклов.Трубопровод II=1 обеспечивает один результат за тактовый цикл после начальной задержки, максимизируя пропускную способность.
  • Петля развертки: воспроизводит петлевые тела для выполнения нескольких итераций параллельно, обменивая область на производительность.
  • Распределение и изменение структуры массивов: разделяет массивы на меньшие банки памяти для параллельного доступа. объединяет разделенные данные в более широкое одно слово памяти.
  • Функция, в которой содержится: ], объединяет функциональные иерархии, предоставляя инструменту больше возможностей для трансграничной оптимизации.
  • Интерфейсные прагмы: Укажите, как подключается верхняя функция — для потоковой передачи, для интерфейса управления с картой памяти, для внешнего доступа к памяти DDR и т.д.
  • Поток данных: обеспечивает параллелизм на уровне задач, позволяя последовательности функций или циклов работать одновременно в качестве трубопровода с потоковыми каналами.
  • Выделение ресурсов: или директивы могут ограничивать количество DSP или портов памяти, предотвращая споры о ресурсах.

Хорошо подобранные прагмы могут означать разницу между дизайном, который едва удовлетворяет пропускной способности, и тем, который оставляет ресурсы бездействовать. Процесс оптимизации является итеративным: применять директивы, синтезировать, проверять отчеты о производительности и использовании и совершенствовать. Ведите журнал, из которого прагмы были опробованы и их влияние на область и задержку.

Шаг 4: Синтез и анализ

Запустите синтез HLS для создания кода RTL и всеобъемлющих отчетов. Наиболее важным отчетом является профиль производительности, показывающий задержку каждого цикла, интервал инициации и глубину трубопровода. Отчет об использовании ресурсов разбивает LUT, флип-флопы, DSP и использование ОЗУ блоков. Перекрестная ссылка на них с емкостью и ограничением часов вашего целевого устройства.

Современные инструменты HLS также генерируют просмотрщик расписания (карту Ганта) и карту связывания, помогая визуализировать, как операции распределены по тактовым циклам и функциональным блокам. Если достигнутый интервал инициации или задержка выше, чем хотелось бы, ищите «зависимости с петлей» или конфликты портов памяти, отмеченные в отчете. Часто тонкая конструкция C - как аккумулятор, зависящий от его предыдущего значения - предотвращает достижение II = 1 без перекодирования или разделения массива. Используйте просмотрщик расписания для точного определения киосков.

Шаг 5: Совместная симуляция C/RTL

Перед интеграцией генерируемого RTL в более крупную конструкцию FPGA проверьте функциональную эквивалентность с помощью ко-симуляции. Инструмент компилирует исходный тестбенч C против генерируемого RTL с помощью пакетного симулятора (например, Xcelium, ModelSim или Vivado Simulator). Он проходит те же векторы ввода и сравнивает цикл выходов по циклу. Ко-симуляция не только подтверждает логическую корректность, но и выявляет несоответствия времени, например, когда модель C предполагает немедленную запись памяти, в то время как RTL имеет задержки записи из-за задержки BRAM.

Если возникают несоответствия, проверьте форму волны или журнал транзакций. Настройте модель C или прагмы (например, добавляя с соответствующей задержкой) до тех пор, пока поведение RTL не совпадет с циклом золотой модели. Хорошей практикой является выполнение совместной симуляции на небольших подфункциях перед масштабированием до полной конструкции, уменьшая итерации отладки.

Шаг 6: экспорт ИС и интеграция в FPGA Design Flow

После проверки экспортируйте дизайн в виде упакованного IP-ядра — обычно в формате IP-XACT или Intel Qsys. Этот IP-блок затем может быть реализован в дизайне блока (например, Vivado IP Integrator) вместе с другими модулями RTL, мягкими процессорами или контроллерами памяти. IP, генерируемый HLS, включает временные ограничения и готов к размещению и маршрутизации.

В традиционном потоке FPGA вы затем запускаете синтез и реализацию (место и маршрут) для создания конечного битового потока. Мониторинг отчетов о сроках реализации тщательно. Инструменты HLS обеспечивают расчетное время на основе моделей предварительного размещения; реальное размещение может выявить более длительные задержки маршрутизации, требующие от вас расслабления целевых часов или пересмотра ограничений HLS. Если цель цикла II не может быть достигнута аппаратным обеспечением, инструмент будет снижать время или дизайн будет не соответствовать времени, поэтому этот цикл обратной связи имеет важное значение. Бюджетный дополнительный слэк (10-20%) во время HLS для учета физических эффектов.

Пример: внедрение FIR-фильтра с HLS

Для закрепления этих концепций рассмотрим фильтр с конечным импульсным откликом (FIR) — общий строительный блок цифровой обработки сигналов. В приведенном ниже коде C реализован 16-ти тизерный фильтр FIR с фиксированными коэффициентами. Мы будем применять прагмы для достижения высокой пропускной способности на AMD Xilinx FPGA.

#include <ap_fixed.h>
#include <hls_stream.h>

typedef ap_fixed<16,8> data_t;
typedef ap_fixed<16,8> coeff_t;

void fir(hls::stream<data_t> &in, hls::stream<data_t> &out, coeff_t coeffs[16]) {
#pragma HLS INTERFACE axis port=in
#pragma HLS INTERFACE axis port=out
#pragma HLS INTERFACE s_axilite port=coeffs
 static data_t shift_reg[16];
#pragma HLS ARRAY_PARTITION variable=shift_reg complete dim=1
 data_t acc = 0;
 // Shift and accumulate
 ShiftLoop:
 for (int i = 15; i > 0; --i) {
#pragma HLS PIPELINE II=1
 shift_reg[i] = shift_reg[i-1];
 acc += shift_reg[i] * coeffs[i];
 }
 shift_reg[0] = in.read();
 acc += shift_reg[0] * coeffs[0];
 out.write(acc);
}

Ключевые прагмы в этом примере:

  • Ось ИНТЕРФЕЙС: Использует AXI4-Stream для ввода и вывода, идеально подходит для непрерывного потока данных.
  • ARRAY PARTITION complete: Разделяет регистр сдвига на отдельные регистры, обеспечивая параллельный доступ ко всем кранам.
  • PIPELINE II=1: Обеспечивает обработку одного нового образца за тактовый цикл после начальной задержки.

После синтеза проверьте отчеты: цикл сдвига должен достигать II=1, а использование ресурсов (DSP для умножения) должно выровняться с 16 множителями. Эта конструкция затем экспортируется в качестве ядра IP и интегрируется в более крупную систему — например, подключается к AXI DMA для потоковой передачи данных с датчика. Этот пример демонстрирует, как несколько прагм переводят простую функцию C в высокопроизводительный аппаратный ускоритель.

Стратегии оптимизации для производительности и области

Эффективная HLS требует балансировки пропускной способности, задержки и потребления ресурсов. Несколько моделей повторяются в успешных проектах.

  • Предпочтите арифметику с фиксированной точкой: Операции с плавающей точкой потребляют значительные ресурсы и ограничивают частоту.Если динамический диапазон не является критическим, используйте типы с фиксированной точкой (например, в Vitis HLS) для уменьшения количества DSP и LUT при сохранении точности.
  • Потоковые данные вместо случайного доступа к памяти: Аппаратные средства наиболее эффективны при прохождении данных по трубопроводу. Используйте или аналогичные потоковые конструкции для подключения задач, избегая больших общих воспоминаний, которые приводят к арбитражным и буферным киоскам.
  • Структурная петля гнездится для идеальной петли гнезд: Инструмент может автоматически прокладывать внутреннюю петлю. Убедитесь, что петли не имеют зависимостей, связанных с петлей, за пределами известных шаблонов (например, редукция). Для свертки или умножения матрицы рассмотрите локальную буферизацию памяти и наклон для использования повторного использования данных.
  • Использовать шаблонное метапрограммирование для настраиваемости: Шаблоны C++ позволяют компилировать временную параметризацию размеров массивов и ширины данных, делая один и тот же источник HLS многоразовым на всех устройствах без потери производительности.
  • Распределение ресурсов и задержка: Директива может заставить делиться дорогостоящих операторов, таких как делители.Однако чрезмерное разделение может сериализовать операции и увеличить задержку; взвесить производительность трубопровода.
  • Использование точного битового типа с умом: Использование жестко типизированных изображений с фиксированной точкой минимизирует стоимость оборудования. Например, для пиксельных данных использует минимальные ресурсы при сохранении необходимой точности. Всегда ошибка квантования профиля против алгоритмической толерантности.

Инструменты HLS также предлагают каталоги «решения», в которых вы можете поддерживать несколько наборов оптимизации (например, «низкая площадь», «высокая пропускная способность») и сравнивать их. Это бесценно для изучения пространства дизайна, не теряя более ранних результатов.

Отладка и проверка передовой практики

Отладка HLS-дизайнов отличается как от программного обеспечения, так и отладкой RTL. Поскольку исходный код C++, традиционные отладчики могут проверять функциональность, но не могут выявить аппаратный параллелизм или ошибки синхронизации. Следующие методы уменьшают боль:

  • Поддерживайте циклоприближённую модель C++, которая использует те же протоколы интерфейса (например, потоковую передачу), чтобы вы могли быстро имитировать.
  • Внедрить самопроверочные тест-системы с рандомизированным генерированием входных данных и золотыми эталонными выходами.
  • Используйте лог и прагматические предупреждения инструмента HLS агрессивно. Относитесь к несинтезируемым конструкциям или субоптимальным петлевым структурам как к ошибкам.
  • Начните симулировать на ранней стадии на небольшом подмодуле, прежде чем масштабироваться до полной конструкции.
  • Используйте встроенный анализ производительности инструмента HLS для просмотра узких мест интервала инициации перед запуском длинных симуляций RTL.
  • Осмотрите сгенерированный код RTL на неожиданные структуры: например, большие мультиплексоры часто указывают на чрезмерно сложные условные ветви. Упростите условия, уплощая вложенные утверждения, где это возможно.

Обычные подводные камни и как их избежать

Даже опытные инженеры сталкиваются с повторяющимися проблемами при переходе на HLS. Распознавание их заранее сглаживает переход.

  • Неограниченные петли: Записи с переменными числами поездок, которые не поддаются исчислению во время компиляции, не могут быть правильно запланированы. Предварительно определить максимальные количества поездок и использовать для руководства инструментом.
  • Большие интерфейсы памяти с плохой пропускной способностью: Один главный интерфейс AXI4-Lite для больших массивов данных будет снижать производительность. Для высокой пропускной способности используйте AXI4-Stream или AXI4 master с преобразованием ширины данных и поддержкой разрыва, контролируемой соответствующими прагмами.
  • Игнорирование сброса и инициализации: В отличие от чистого RTL, HLS иногда предполагает, что регистры могут начинаться в действительном состоянии. Убедитесь, что у вас есть стратегия чистого сброса и избегайте неинициализированных локальных массивов, которые могут вывести неинициализированные ОЗУ (используйте , где это необходимо).
  • Опираясь на автоматическую оптимизацию инструмента: Хотя инструменты HLS являются мощными, они не могут угадать намерение проектирования. Простой протокол рукопожатия может потребовать явного выбора интерфейса , чтобы соответствовать ожидаемому поведению; полагаясь на по умолчанию, может привести к несоответствию интерфейсов.
  • Пренебрежение реальными временными ограничениями: Планирование HLS использует простую модель времени. Физическое размещение сетей с высоким коэффициентом отказов или больших мультиплексоров может вызвать неожиданные нарушения времени. Бюджетное дополнительное слакс — целевое время на 10-20% выше, чем предполагаемый максимум HLS.
  • Забывание проверки киосков трубопровода: В трубопроводной петле, если входной поток кипит, трубопровод должен быть в состоянии стекать без застоя. Используйте интерфейсы, учитывающие обратное давление, и проверьте поведение киосков в ко-симуляции.

Интеграция HLS с гетерогенными системами

Современные платформы FPGA сочетают программируемую логику с системами жестких процессоров (например, ARM Cortex в Zynq, Agilex SoC). HLS естественным образом вписывается в эти архитектуры. Обычный шаблон заключается в использовании процессора для управления и настройки ускорителя, генерируемого HLS, через AXI-Lite, в то время как потоки данных с высокой пропускной способностью через AXI4-Stream или AXI4-мастерские порты. Документация Vitis HLS обеспечивает обширное руководство по интеграции с Xilinx Runtime (XRT) и OpenCL API. Аналогично, компилятор Intel HLS в рамках одной API позволяет одному и тому же коду ядра C++ нацеливаться как на процессоры, так и на FPGA, упрощая разработку реконфигурируемых ускорителей.

Для систем управления в реальном времени HLS может генерировать пользовательское периферийное устройство RTL, которое взаимодействует с межсоединением AXI процессора, обрабатывая критически важные по времени ввода-вывода, в то время как процессор управляет политиками и сетевыми стеками. Это разделение труда максимизирует производительность, не жертвуя гибкостью. При проектировании таких систем обратите внимание на соответствие ширины данных: мастер AXI4 с 64-битным интерфейсом может потребовать логику выравнивания разрыва в ядре HLS.

Будущее синтеза высокого уровня

HLS быстро развивается, улучшая эвристику компиляторов, формальную проверку и библиотечные экосистемы. Впереди несколько тенденций:

  • Машинное обучение для HLS в стиле AutoML: Инструменты начинают включать модели ML, которые предсказывают оптимальные конфигурации прагмы, уменьшая ручную настройку. Исследования как из академических кругов, так и из промышленности направлены на создание синтеза «кнопки», который конкурирует с экспертными проектами.
  • Стандартизация вокруг C++17 и за его пределами: Поскольку интерфейсы HLS принимают современные стандарты C++, дизайнеры могут использовать constexpr, лямбда и метапрограммирование шаблонов для написания высокопараметризированных многоразовых аппаратных библиотек.
  • Ближе интеграция с высокоуровневой верификацией: Универсальная методология верификации (УВМ) и моделирование уровня транзакций SystemC объединяются с HLS для создания унифицированных потоков проектирования и проверки, уменьшая узкое место верификации.
  • Аппаратные стека с открытым исходным кодом: Такие проекты, как CHIPS Alliance, способствуют открытию фреймворков и библиотек HLS, что делает HLS более доступным за пределами основных поставщиков FPGA.
  • Повышенная поддержка динамической реконфигурации: Будущие потоки HLS могут позволить замену ядер во время выполнения, что позволяет адаптивным системам перенастраиваться в ответ на изменение рабочих нагрузок.

По мере того, как плотность FPGA продолжает расти, управление сложностью на уровне RTL становится неустойчивым. HLS предлагает способ управления этой сложностью, повышая уровень абстракции, сохраняя при этом эффективность аппаратного обеспечения. Освоение HLS теперь позиционирует инженеров для создания следующего поколения высокопроизводительных, реконфигурируемых систем, от периферийных ускорителей ИИ до высокоскоростного сетевого оборудования.