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

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

В 1990-е было много проектов такого рода, в том числе и мой собственный, под которое даже удалось получить финансирование от Интела и продать лицензии в Hitachi, Motorola и другие компании. На эту тему было много вариаций: CycleC, CynApps, Frontier, Napa-C, TrasmogrifierC, SpecC, Handel-C, IMEC OCAPI, CatapultC и другие. Ну и SystemC разумеется, про который у меня есть отдельная заметка.

Из презентации Эльяра Гасанова похоже что ИРИС использует подход, при котором они создают 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 декодера, но для гетерогенных систем на кристалле это не скейлится. Данная тема возникла из вопроса девушки докладчику:

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

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 вообще нет.

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

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

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

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

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

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

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

Комментарии (24)


  1. helmm
    04.06.2024 06:45
    +1

    Странно, конечно, столько всего упомянуто, а SystemC не упомянут, хотя казалось бы он максимально сильно распространён в сравнении с альтернативами опирающимися на C/C++.
    ИРИС надо понимать в рамках импортозамещения задуман, т.к. всё остальное иностранное (C++, конечно тоже иностранный, но "это другое", "тут понимать надо").


    1. YuriPanchul Автор
      04.06.2024 06:45
      +1

      Да, разумеется, просто SystemC настолько известен, что я его пропустил. Сейчас добавлю. При этом в SystemC event queue есть, то есть это не просто update каждый такт старого значения на новое и перевычисление нового.


    1. YuriPanchul Автор
      04.06.2024 06:45

      Да, разумеется, просто SystemC настолько известен, что я его пропустил. Сейчас добавлю. При этом в SystemC event queue есть, то есть это не просто update каждый такт старого значения на новое и перевычисление нового.


    1. YuriPanchul Автор
      04.06.2024 06:45
      +1

      Про SystemC у меня есть отдельная заметка - https://panchul.livejournal.com/473865.html


      1. checkpoint
        04.06.2024 06:45
        +1

        Прочитал, спасибо. Мне потребовалась одна ночь повозиться с SystemC чтобы понять, что это полный фуфел. Оказывается мировой индустрии потребовалось не менее 10 лет чтобы прийти к тому же заключению. :)


        1. YuriPanchul Автор
          04.06.2024 06:45
          +1

          Дизайнеры матюкались на SystemC сразу в 1998-1999, когда менеджеры просили их попробовать то, что им впаривали продажники Synopsys. Поэтому продажники стали пробовать другие категории пользователей, но я знаю абсолютно точно, что они не продали ничего за деньги, потому что в 2002 году шел по коридору, заглянул на презентацию продажников и увидел там жирный ноль. То есть до этого они четыре года пытались, чтобы клиенты пользовали это бесплатно, но те отбрыкивались даже так. При этом синопсис в статьях говорили "вся индустрия выстроилась за нами". Потом они нашли писателей моделей в Европе и смогли продать им историю про "более высокий уровень моделирования" используя абстракции для интерфейсов от CoWare.


  1. rukhi7
    04.06.2024 06:45
    +1

    использует подход, при котором они создают C++ классы для reg и wire (внутри которых вероятно старое и новое значение для такта), потом переопределяют операции, и таким образом реализуют функционал верилога в C++

    Такое ощущение что это так завернуто чтобы никто не придирался, на самом деле, если выражаться максимально просто, суть в том что это просто попытка

    писать дизайн (цифровую схему) на С++, вместо того чтобы писать ее на верилоге (VHDL-е?)

    Естественно на С++ приходится оперировать классами которые в свою очередь должны как-то отображаться на объекты предметной области, то есть на reg и wire объекты.

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

    При таком узком понимании задачи вряд ли получится что-то из этой попытки. Я так думаю.


  1. Seraffo
    04.06.2024 06:45
    +1

    Мне тоже показалось, что разработка ИРИС сродни внутренним DSL больших компаний-разработчиков железа. И основное его преимущество — автором языка так писать удобней.

    От меня: понятно, что ИРИС заточен на перенос в hardwar'ные ядра функциональных описаний вычислительных алгоритмов ( в виде, например, С-кода). То что в ИРИС невыразимы клоковые домены ярко это подчеркивает.


  1. checkpoint
    04.06.2024 06:45
    +2

    SystemC с точки зрения синтаксиса и семантики - полное и бесповоротное г@вно! Писать нанём что либо можно только со страшной скуки или за катастрофически большие деньги.

    На счет ИРИС. Докладчик почти не привел никаких примеров. Хочется посмотреть как выглядят на ИРИС типовые вещи, тот же FIFO с кодом Грея, какой нибудь конвейер. Так же хочется посмотреть на исходник какого нибудь серьезного пректа (например вычислительного ядра). После можно будет сказать лучше это или хуже для разработки сложных проектов. В больших проектах скорость симуляции это второстепенный показатель (Verilator решает и эту проблему, так как транслирует Verilog в Си), а первостепенным является локаничность кода, его прозрачность и незамутненность всякими прагмами и прочей управляющей шелухой, а также понятный вывод сообщений об ошибках. В этом смысле SpinalHDL и Chisel очень хороши. Если этим парням из МГУ удастся сделать что-то близкое на C++, то это будет хорошо. Еще лучше если они снабдят свой язык библиотекой классов для типовых задач, перепишут на ИРИС ходовые IP блоки (I2C, SPI, AXI, MAC, DDR), опубликуют под опенсорсной лицензией и будут поддерживать даже если финансирование от Минпромторга иссякнет. А пока что это выглядит так: "мы тут сидим, лудим, паяем, примус починяем, и тут к нам приходит Минпромторг...".

    Такие будут мои пять копеек.


    1. YuriPanchul Автор
      04.06.2024 06:45
      +1

      SystemC изначально написали вроде два каких-то студента из Германии в 1996 году и у меня ощущение, что они вдохновлялись вышедшей в том время библиотекой Микрософта для Windows MFC. А Synopsys взяли это под крылышко чтобы вытянуть другой непопулярный продукт (Behavioral Compiler) и вероятно под влиянием маркетеров. Там много стремных вещей, например возможность дедлоков если использовать не SC_THREAD, а SC_METHOD (долго рассказывать). Кое-что есть в моем посте https://panchul.livejournal.com/473865.html


    1. KeisN13
      04.06.2024 06:45
      +1

      Судя по докладу, ИРИС подходит больше для реализации алгоритмов, чем для интерефесов.


      1. YuriPanchul Автор
        04.06.2024 06:45
        +1

        Комбинационная и последовательностная логика, выраженная в reg и wire, что для вычислительных конвейеров, что для FSM, что для интерфейсов типа AXI должны работать одинаково в принципе.


    1. YuriPanchul Автор
      04.06.2024 06:45
      +1

      А в чем классность Spinal HDL? На первый взгляд куча лишнего синтаксиса:

      Chisel используют только в Беркли и SiFive, причем в SiFive новых инженеров ему месяца три учат. То есть я не вижу смысла использовать его в образовательных программах - он отберет время от микроархитектуры и не поможет в трудоустройстве в подавляющее большинство компаний на рынке.


      1. checkpoint
        04.06.2024 06:45

        Юрий, приведенный пример не очень репрезентативен. На самом деле в SpinalHDL/Chisel кода получается как раз меньше чем на Verilog-е и он более логично организован: нет блоков always() которые сильно режут код на части и затрудняют понимание; семантика оператора присваивания зависит от типа сигнала; сбросы и клоки скрыты и их не нужно таскать с собой как чемодан без ручки и выполнять над ними ритуальные действия, и много еще разных мелки удобств. Единственное, что меня сейчас напрягает в SpinalHDL это то, что часто приходится явно приводить типы (или размеры) сигналов, а это дополнительный код (пролоема решается созданием совего класса для сигнала и переопределением соответствующих операторов). Но с другой стороны, сразу видно что и во что преобразуется, а не как в Verilog-е где одна и та же константа может синтезироваться во что угодно. ;-) Короче, более сложные вещи получается существенно короче и понятней. Тут не попробуешь - не поймешь. :)

        На счет востребованности специалистов. Разумеется это не мейнстрим и спрос на спецов знакомых с этими языками ничтожно мал. Но опять же, в 90-х подавялющее большинство программистов писали на C/C++ и никто даже не считал нужным преподавать что-то иное, а сейчас все пишут на Python потому что это существенно проще и не заставляет программиста заморачиваться проблемами распределения памяти. В таких высокоуровневых HDL как Spinal и Chisel все то же самое - разрабочик сосредотачивается на задаче (на микроархитектуре как Вы говорите), а не на тонкостях компиляции/синтеза.

        И еще. То, что приследовали разработчики ИРИС - моделирование, верификация и синтез в одном и том же коде. Мне хотелось бы видеть ИРИС как вариант SpinalHDL, но на C++.


        1. YuriPanchul Автор
          04.06.2024 06:45

          "Попробуйте - узнаете" я не принимаю. Всегда должен быть пример кода, в котором получается более кратко, чем с SystemVerilog generate например. Мне такое показывали с строенным в верилог перлом и пример когда Chisel генерит интерконнект для большого количества регионов памяти.


          1. checkpoint
            04.06.2024 06:45
            +1

            Ну вот из приведенного Вами примера, строка на SpinalHDL:

            val register = Reg(UInt(width bits)) init(0)

            будет преобразована в Verilog:

                logic [width - 1:0] register;
            
                always_ff @ (posedge clk or posedge rst)
                    if (rst)
                        register <= '0;

            Или вот другой пример, из моей статьи.

            Код на SpinalHDL:

            case class MyTopLevel() extends Component {
              val io = new Bundle {
                val cond0 = in  Bool()
                val cond1 = in  Bool()
                val flag  = out Bool()
                val state = out UInt(8 bits)
              }
            
              val counter = Reg(UInt(8 bits)) init 0
            
              when(io.cond0) {
                counter := counter + 1
              }
            
              io.state := counter
              io.flag := (counter === 0) | io.cond1
            }

            Выдаст код на Verilog вида:

            module MyTopLevel (
              input  wire          io_cond0,
              input  wire          io_cond1,
              output wire          io_flag,
              output wire [7:0]    io_state,
              input  wire          clk,
              input  wire          reset
            );
            
              reg        [7:0]    counter;
            
              assign io_state = counter;
              assign io_flag = ((counter == 8'h00) || io_cond1);
            
              always @(posedge clk or posedge reset) begin
                if(reset) begin
                  counter <= 8'h00;
                end else begin
                  if(io_cond0) begin
                    counter <= (counter + 8'h01);
                  end
                end
              end
            
            
            endmodule

            Здесь код на SpinalHDL понятен даже для человека ранее не сталкивавшегося с HDL. А вот код на Verilog понятен только для посвященных.


            1. YuriPanchul Автор
              04.06.2024 06:45

              А зачем использовать выдачу автоматического конвертера для сравнения? В причесанном виде этот код выглядит так. И я вообще не покупаю аргумент что Spinal якобы понятнее. Для Scala - программиста - может быть, но я знаю 1 Scala программиста и сотни Verilog пользователейю

              module MyTopLevel
              (
                input              io_cond0,
                input              io_cond1,
                output             io_flag,
                output logic [7:0] io_state,
                input              clk,
                input              reset
              );
              
                assign io_flag = io_state == '0 | io_cond1;
              
                always_ff @(posedge clk or posedge reset)
                  if (reset)
                    io_state <= '0;
                  else if (io_cond0)
                    io_state <= io_state + 1'b1;
              
              endmodule


              1. checkpoint
                04.06.2024 06:45

                Юрий, ну Вы же не станете отрицать, что код на Scala понятен даже питонисту, ибо синтаксис тривиален (на самом деле нет, но на первый взгляд кажется таким) и общепринят во многих других языках. В то время как код на Verilog-е понятен только пользователю Verilog.

                А теперь вернемся к "устоявшейся традиции" описывать отдельный блок always для каждого регистра и мы получаем страшную портянку на Verilog испещренную кусками текста вида away / if(reset).


                1. YuriPanchul Автор
                  04.06.2024 06:45

                  А теперь вернемся к "устоявшейся традиции" описывать отдельный блок always для каждого регистра

                  Нет такой устоявшейся традиции. Просто нет. То есть абсолютно. Я не видел ни в одной компании. Есть компании (Интел, MIPS), где в некотором старом коде были instances для регистров и куча assigns, и есть компании, где бОльшую часть комбинационной логики описывают в always_comb и потом небольшое количество кода в always_ff обновляет регистры, но так чтобы на каждый регистр - отдельно always-блок - такого не видел. Отдельные блоки для resettable flip-flops и не-resettable - да, бывают. Но не always на каждый регистр.


                  1. checkpoint
                    04.06.2024 06:45

                    Юрий, я не хочу продолжать этот спор потому как у меня просто не хватает квалификации - Вы всё равно меня обставите со всех сторон. :) Но глядя на всё это дело со стороны, я вижу, что писать на SpinalHDL существенно проще и понятней.

                    Вообще, я смотрю на это дело так: Verilog это своего рода хардверный ассемблер, в то время как Spinal/Chisel/Amaranth это "C++" или даже "Python". Как человек выросший на ассемблерах и "голом Си" я предпочту писать низкоуровневый код на Verilog, но всю обвязку, архитектуру и тестбенчи я предпочту сделать на Spinal.

                    Кстати, в SpinalHDL очень просто интегрируются готовые блоки на Verilog. Пример:

                    case class TMDS_encoder() extends BlackBox{
                            val clk = in Bool()
                            val VD = in Bits(8 bits)
                            val CD = in Bits(2 bits)
                            val VDE = in Bool()
                            val TMDS = out Bits(10 bits)
                    }

                    При компиляции подкидываем файл .v (.vs) содержащий модуль TMDS_encoder и весь сказ.


                    1. YuriPanchul Автор
                      04.06.2024 06:45

                      Я ровно такой же пример написал, но только на C++ , аж в 1996 году. Тоже class counter : module { Input<4> a; итд. Пошёл к Расселу Клайну, маркетеру в Mentor Graphics. Он мне сказал: это очень мило, но рынок хочет другого. И он был прав. Это вообще первая идея, которая приходит каждому ООП программисту при виде верилога (переписать verilog или vhdl на c++ или джаву)


                1. YuriPanchul Автор
                  04.06.2024 06:45

                  Про скалу - слова class, extends, new не дают никакой информации для схемы и являются артифактами OOP. Не покупаю такое.


                  1. checkpoint
                    04.06.2024 06:45

                    Но для любого программиста это же очевидные вещи ? :)


                    1. YuriPanchul Автор
                      04.06.2024 06:45

                      Я был таким программистом в 1996 году (см. коммент выше)