Мысли по поводу доклада на FPGA-Systems про маршрут ИРИС из МГУ

a588f26e3741e0e021d83273528f2e0c.png

На конференции FPGA-Systems был предоставлен маршрут проектирования блоков микросхем на основе использования C++ под названием ИРИС. Докладчик — заведующий кафедрой Мехмата МГУ Эльяр Гасанов. Его группа имеет значительный опыт проектирования оптимизированных по производительности блоков, например LDPC декодера, и ведет свои истоки из сотрудничества с LSI Logic в середине 1990-х годов.

Мои мысли после просмотра презентации:

В 1990-е было много проектов такого рода, в том числе и мой собственный, под которое даже удалось получить финансирование от Интела и продать лицензии в Hitachi, Motorola и другие компании. На эту тему было много вариаций: CycleC, CynApps, Frontier, Napa-C, TrasmogrifierC, SpecC, Handel-C, IMEC OCAPI, CatapultC и другие. Из презентации Эльяра Гасанова похоже что ИРИС использует подход, при котором они создают C++ классы для reg и wire (внутри которых вероятно старое и новое значение для такта), потом переопределяют операции, и таким образом реализуют функционал верилога в C++. По тактам (cycle-accurate), то есть очереди событий (event queue) у них под этим нет.

Достоинства и недостатки такого метода:

1. Достоинство: Можно использовать в качестве дизайнеров людей, которые знают C++, но не знают верилог. Недостаток: если дать такое дизайнеру, который знает верилог, но не знает C++, то он будет очень недоволен, когда ему придется понимать сообщения об ошибках, возникающих внутри templated C++ классов.

2. Если компилятор C→Verilog поддерживает сложные типы данных (массив структур из массивов структур) и транслирует их корректно в параллельные массивы на Verilog-95, то это было круто в 1990-е и начале 2000-х, но перестало быть актуальным с введением структур и многомерных портов в SystemVerilog в начале 2000-х и поддержке их синтезом в районе 2010 года.

Кстати докладчик упоминает, что типизированные сигналы (структурного типа) они добавили только после критики от Минпромторга. То есть в исходном продукте у них были только битовые вектора.

3. Достоинство: можно комбинировать модели на Си c написанным таким образом дизайном, без промежуточных перемычек через интерфейс DPI. Недостаток: когда код на Си будет странслирован в верилог, такие перемычки ставить все равно придется для косимуляции Си и верилога и они будут bottleneck в симуляции, а также вызывать дедлоки, когда внутри Си модели происходит что-то, что требует нескольких тактов, а коду на верилоге нужно работать параллельно с этим.

4. Проблема: дополнительный шаг в маршруте к статическому анализу тайминга. Код на Си нужно транслировать в верилог, чтобы запустить static timing analysis, и потом из его отчета (на основе переменных в верилоге) придется понимать какой код в Си вызвал negative slack на данном критическом пути.

Докладчик упомянул, что у них есть оптимизации критического пути, но не привел данных, насколько их оптимизации улучшают по сравнению с существующими оптимизациями в Synopsys Design Compiler, Cadence Genus, Open Lane, Xilinx Vivado и Altera Quartus (5 точек для сравнения которые выбрал бы я).

5. Достоинство: можно сделать C++ классы для чисел с фиксированной точкой, насыщением и округлением, и транслировать это в верилог. Это было полезно для DSP, когда такое сделал в свое время Frontier Design. Проблема: транслятор нужно делать очень аккуратно, чтобы точно передать разницу в семантике знаковых и беззнаковых чисел, а также контекста присваивания в верилоге, где результат сложения двух 4-битных переменных может быть 5-битным, а может и нет.

6. Утверждение Эльяра Гасанова, что самой затратной часть проекта является создание RTL кода — не совсем верно — траты на верификацию могут быть и больше, а в описывамой технологии нет аналогов функционального покрытия, решателей ограничений (constraint solver) для псевдо-случайных транзакций, аналога языка утверждений SVA и разных других фич которые есть в SystemVerilog. Есть toggle coverage.

Вообще тесты которые применяются с модулями на ИРИС уже после трансляции в верилог и реализации в ПЛИС описывались как довольно прямолинейные, в духе начала 1990-х годов: файлы со стимулами и ожидаемым результатами. Это может быть достаточно для LDPC декодера, но для гетерогенных систем на кристалле это не скейлится. Данная тема возникла из вопроса девушки докладчику:

36c5e35c69308c39f028e12cfe8fd85d.png

Вообще молодая аудитория задавала дельные вопросы по существу. Вот еще девушка спросила какой стандарт верилога (Verilog-95, Verilog-2001, SystemVerilog-2005/…/2023) выводит тул. Я бы на ее месте задал бы вопрос более коварно: если ИРИС (по запросу Минпромторга) поддерживает типизированные сигналы, то во что превращается C++ struct при конверсии — в битовые вектора (reg/wire) или в SystemVerilog struct/typedef, а?

ea0983ce1e4ac9af04ff3943eda36163.png

7. Я не увидел в подходе возможности отладки в дополнение к: 1) обычному отладчику на Си, 2) самопроверки в классах (скажем ширины в битах) и 3) просмотру VCD дампа (waveforms). Очень существенная возможность отладки на верилоге в средах Synopsys Verdi и Cadence SimVision — это хождение мышкой по drivers / loads — источникам значения сигнала, в том числе в предыдущих тактах, и сигналам, на которые данный сигнал влияет.

Небольшое отступление:

Я думаю, что отсутствие хождения по drivers / loads в скажем Mentor Questa — это главная причина почему квесту редко используют ASIC компании в США (квеста больше, субъективно, для бюджетного дизайна FPGA и образования). В дизайнах больших процессоров, GPU, сетевых чипов, в которых миллионы сигналов, без такого хождения не обойтись. Когда в каком-то такте сигнал A какой-то не такой, то я автоматически нажимаю правой кнопкой мышки (в Verdi и SimVision) на его источники B, С, добавляю их в waveform, потом смотрю что происходит с ними, откатываю назад на такт, если они в регистрах, и иду назад во времени, проходя через регистры и FIFO, пока источник ошибки не станет очевиден. Еще круче это делают тулы для формальной верификации типа Jasper Gold, но это отдельная тема, а я говорю про обычную динамическую симуляцию. И вот в ИРИС такое, насколько я понимаю, трудно сделать, отследить цепочку событий в разных тактах, которая привела к текущему результату.

Видео от Synopsys и Cadence на тему: 1, 2, 3.

8. Фундаментальная проблема: подход ИРИС не повышает уровень с RTL до алгоритмического, а также (судя по слайдам) не позволяет описывать конвейеры неким высокоуровневым способом, и следовательно не приводит к существенному повышению производительности труда дизайнера.

Пример существенного повышения производительности из прошлого — переход от ввода схем в графическом виде (schematic entry) к использованию языков описания аппаратуры.

Впрочем, докладчик это понимает и продвигает скорее повышение удобства разработки на том же уровне абстракции.

9. Конечно можно говорить про снижение порога входа за счет использования языка C++ со знакомым синтаксисом, но проблема в том, что такой подход никак не снижает порог в понимании принципов последовательностной логики (в каком такте происходит что), а этот порог больше, чем выучивание конструкций module/порты/always итд.

10. Планы о создании транслятора Verilog → ИРИС имеют ИМХО скорее академический интерес, нежели практический. Я в 2001 году написал, помимо трех вариантов трансляторов C/C++ → Verilog, еще и транслятор Verilog → CycleC при продаже своего стартапа Synopsys-у, а потом работал в группе VCS Синопсиса 2 года. Поэтому я понимаю проблемы которые нужно решить при написании обратного транслятора, и не вижу где такой транслятор выиграет по сравнению с Synopsys VCS или Cadence Xcelium в производительности, особенно в крупных дизайнах (в небольших Synopsys и Cadence слишком долго стартуют) и при установке всех опций оптимизации типа «выключить поддержку X/Z значений». А выигрыш по сравнению с скажем Икарусом — это не выигрыш (c Verilator — тут смотреть надо). В табличке сравнения ИРИС Synopsys и Cadence вообще нет.

82fc277a22b9bb311cefc4ab26bfc9a7.png

Мерять скорость симуляции только по блоку LDPC скорее всего тоже некорректно. Он может оказаться в классе дизайнов, в которых все стадии конвейера перевычисляют значения каждый такт, и тогда компилируемая потактовая симуляция будет быстрее чем компилируемая симуляция на основе очереди событий. А если реализовать по этой методологии кластер из процессоров, в которых бОльшая часть дизайна бОльшую часть тактов ничего не делает (спит)? И этот сон желательно не перевычислять? Я делал такое упражнение в 2002 году с дизайнами клиентов Синопсиса и обнаружил, что подобная методология (CycleC) работает блестяще на избранных демо-дизайнах, но на всех остальных надо долго искать положительный пример именно из-за этого эффекта.

Если же речь идет не о производительности, а о генерации читабельного кода на ИРИС C++ классах для последующего использования, то такое можно сделать, но сколько у такого продукта будет пользователей? Обратный маршрут имеет смысле при наличии большого количества пользователей у прямого маршрута (ИРИС → Verilog).

В защиту подхода

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

Вообще, внутри электронных компаний навалом проприетарных языков (domain-specific languages). Обратим внимание на замечание докладчика, что в среде ИРИС не нужно писать always-блоков, а регистры инстанциируются в явном виде. Похожая методология (регистры в виде явных инстансов и куча assign вокруг них) была насколько я слышал внутри Интела, а также внутри MIPS в проприетарном препроцессоре верилога. Для многих людей это повышает ясность дизайна, особенно когда дизайн является конвейерным.

Если писать на верилоге в совсем свободном стиле, например смешивать блокирующие и неблокирующие присваивания в одном always-блоке, то получится код, в котором неочевидно что порождает D-триггер, что провод, в какой переменной значение D на входе D-триггера, а в какой Q на выходе. В таком дизайне черт ногу сломит, а также будут возникать непонятно откуда лишние мультиплексоры из-за порождения D-триггера внутри вложенного «if». А в формате языка ИРИС и его аналогах такая проблема появиться не может, потому что, насколько я понял презентацию, нет лишнего кода внутри clocked always-блоков. Все либо комбинационная логика, либо явные регистры — полный ордунг. И хорошо.

Также слайд про текущие разработки на кафедре Эльяра Гасанова показывает, что у его студентов и аспирантов есть интересные и полезные для их будущего проекты: написать свой статический анализ тайминга, генератор модуля для автоматического пересечения тактового домена или тул для автоматического порождения конвейера (retiming) — это правильные курсовые и дипломные работы, а в развесистом варианте и диссертации. Независимо от входного языка (верилога, си, чизела или еще чего-нибудь более экзотического, хаскела там, или даже, не к ночи будет помянуто, питона):

289d30ed2f679f0ce09f3083b17c7a6f.png

© Habrahabr.ru