Собственный Софт-Процессор На Fpga С Компилятором Языка Высокого Уровня Или Song Of The Mouse

Собственный софт-процессор на ПЛИС с компилятором языка высокого уровня или Песня Мышки - опыт адаптации компилятора языка высокого уровня к многоядерному процессорному ядру.

Распространенной проблемой программных процессоров является отсутствие средств разработки для них, особенно если их набор инструкций не является подмножеством инструкций одного из популярных процессорных ядер.

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

Прямое решение — создать компилятор языка ассемблера.

Однако в современных реалиях не всегда удобно работать в сборке, так как в ходе разработки проекта система команд может меняться из-за, например, изменившихся требований.

Поэтому задача простой реализации компилятора языка высокого уровня (HL) для программного процессора является актуальной.

Компилятор языка Python - Уж представляется простым и удобным инструментом разработки программного обеспечения для программных процессоров.

Инструментарий для определения примитивов и макросов как функций целевого языка позволяет реализовать критические места в ассемблере процессора.

В данной статье рассмотрены основные моменты адаптации компилятора для процессоров стековой архитектуры.

Вместо эпиграфа: Если взрослая мышь Возьми его и, бережно держа, Набейте его иголками Вы получите ёжика.

Если этот ежик Я заткнул нос, чтобы не мог дышать, Где-нибудь поглубже, бросьте его в реку У вас получится ерш.

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

Если это правда, Подготовив два ножа.

Однако он, вероятно, умрет Но идея хорошая!



Введение

Во многих случаях при внедрении средств измерений и исследовательского оборудования предпочтительно использовать реконфигурируемые решения на базе ПЛИС/ПЛИС в качестве основного ядра системы.

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

Для широкого спектра задач, таких как цифровая обработка сигналов, встроенные системы управления, системы сбора и анализа данных, хорошо зарекомендовавшим себя подходом является объединение в одном решении блоков, реализуемых логикой ПЛИС для критических процессов, и программных элементов управления на базе одного или нескольких несколько программных процессоров для общего управления и координации, а также для реализации взаимодействия с пользователем или внешними устройствами/узлами.

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



Типичные «списки желаний»

Часто в этом случае от программных процессоров не требуется сверхвысокая производительность (поскольку ее проще достичь за счет использования логических и аппаратных ресурсов ПЛИС).

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

Их может быть много, и каждый из них может выполнять только определенный набор алгоритмов или подпрограмм.

Ширина программных процессоров также может быть любой, в том числе не кратной байту, в зависимости от требований текущей задачи.

Типичными целями программных процессоров являются:

  • достаточная функциональность системы команд, возможно, оптимизированная под поставленную задачу;
  • высокая плотность программного кода, поскольку это позволит сэкономить ресурсы памяти ПЛИС;
  • компактность — не хотелось бы, чтобы вспомогательные элементы занимали дефицитные ресурсы программируемой логики.

Конечно, некоторой проблемой для программных процессоров является отсутствие для них средств разработки, особенно если их набор инструкций не является подмножеством инструкций одного из популярных процессорных ядер.

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

Ее прямое решение — создать компилятор языка Ассемблера для программного процессора.

Однако в современных реалиях не всегда удобно работать в сборке, особенно если в ходе разработки проекта система команд будет меняться из-за, например, изменившихся требований.

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



Исходные компоненты

Этим требованиям стековые процессоры отвечают с высоким процентом соответствия, поскольку нет необходимости обращаться к регистрам; ширина команды может быть небольшой.

Объем данных для них может варьироваться и не привязан к емкости системы команд. Являясь де-факто (хотя и с небольшими оговорками) аппаратной реализацией промежуточного представления программного кода при компиляции (виртуальная стековая машина, или в терминах контекстно-свободных грамматик - машина хранения), позволяет транслировать грамматику любого языка в исполняемый код с низкими трудозатратами.

Кроме того, язык Форт является практически «родным» языком для стековых процессоров.

Трудозатраты на реализацию Форт-компилятора для стекового процессора сопоставимы с затратами на Ассемблер, с гораздо большей гибкостью и эффективностью реализации программ в будущем.

Имея задачу построить систему сбора данных с интеллектуальных датчиков в режиме, близком к реальному времени, был использован процессор Форт, описанный в работах [ 1 ] (в дальнейшем его иногда будут называть процессором whiteTiger по нику его автора).

Его основные особенности:

  • отдельные стеки данных и возврата;
  • Гарвардская архитектура организации памяти (отдельная память программ и данных, включая адресное пространство);
  • расширение периферийными устройствами с использованием простой параллельной шины.

  • Процессор не использует конвейер; выполнение команды двухтактное:
    1. получение инструкций и операндов;
    2. выполнение команды и сохранение результата.

Процессор дополнен загрузчиком программного кода UART, позволяющим изменять исполняемую программу без перекомпиляции проекта для ПЛИС.

Учитывая конфигурацию блочной памяти в ПЛИС, ширина команды установлена равной 9 бит. Ширина данных установлена на 32 бита, но в принципе может быть любой.

Код процессора написан на VHDL без использования каких-либо специфических библиотек, что позволяет работать с данным проектом на ПЛИС любого производителя.

Для относительно широкого применения, снижения «порога входа», а также для повторного использования кода и применения кодовых разработок целесообразнее переходить на язык, отличный от Форта (отчасти это связано с суевериями и заблуждениями основных программистов относительно сложности этого языка и читаемости его кода (кстати, аналогичного мнения о Си-подобных языках придерживается один из авторов этой работы)).

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

2 ].

Для начинающих разработчиков интересно его расширение MyHDL[ 3 , 4 ], что позволяет описывать аппаратные элементы и структуры на Python и переводить их в код VHDL или Verilog. Некоторое время назад был анонсирован компилятор «Уж»[ 5 ] - небольшой компилятор для программного процессора FPGA Zmey (32-битная стековая архитектура с поддержкой многопоточности - если проследить цепочку версий/модификаций/проверок - Zmey - дальний потомок процессора whiteTiger).

Уж также представляет собой статически скомпилированное подмножество Python, основанное на перспективном наборе инструментов raddsl (инструментарий для быстрого прототипирования DSL-компиляторов) [ 6 , 7 ].

Таким образом, факторы, повлиявшие на выбор направления работы, можно сформулировать примерно так:

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



Мелкие, «почти» бессмысленные нюансы

Исходный код процессора Zmey не открыт, но доступно описание принципов его работы и некоторых архитектурных особенностей.

Хотя он также является стекируемым, он имеет ряд ключевых отличий от процессора whiteTiger:

  • стеки являются программными — т.е.

    представлены указателями и расположены в памяти данных по разным адресам;

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

Соответственно, компилятор УЖ учитывает эти особенности.

Компилятор принимает код Python и на выходе генерирует загрузочный поток для инициализации памяти программы и памяти данных процессора; Ключевым моментом является то, что весь функционал языка доступен на этапе компиляции.

Чтобы установить компилятор Уж, достаточно скачать его архив и распаковать в любую удобную папку (лучше следовать общим рекомендациям для специализированного ПО – избегать путей, содержащих кириллические символы и пробелы).

Вам также необходимо скачать и распаковать набор инструментов raddsl в основную папку компилятора.

В папке test компилятора находятся примеры программ для программного процессора, в папке src — исходные тексты элементов компилятора.

Для удобства использования лучше создать небольшой батник (расширение .

cmd) с содержимым:

   

c.py C:\D\My_Docs\Documents\uzh-master\tests\abc.py

, где abc.py — имя файла с программой для программного процессора.



Змея, кусающая себя за хвост или скрежетающая аппаратным и программным обеспечением

Для адаптации Ужа к процессору whiteTiger потребуются некоторые изменения, а также придется немного подкорректировать сам процессор.

К счастью, в компиляторе не так много мест, которые нужно корректировать.

Основные «аппаратно-зависимые» файлы:

  • asm.py — ассемблер и генерация чисел (литералов);
  • gen.py — правила генерации низкоуровневого кода (функции, переменные, переходы и условия);
  • stream.py – генерация потока загрузки;
  • macro.py — определения макросов, по сути — расширения базового языка с аппаратно-специфичными функциями.

В исходной конструкции процессора whiteTiger загрузчик UART позволяет инициализировать только программную память.

Алгоритм работы загрузчика прост, но проверен и надежен:

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

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

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

Для этого вводятся дополнительные сигналы DataDinBtemp, LoaderAddrB, DataWeBtemp — данные, адрес и разрешение на запись для порта В памяти.

Код загрузчика теперь выглядит так:

uart_unit: entity work.uart --uart_unit: entity uart Generic map( ClkFreq => 50_000_000, Baudrate => 115200) port map( clk => clk, rxd => rx, txd => tx, dout => receivedByte, received => received, din => transmitByte, transmit => transmit); process(clk) begin if rising_edge(clk) then if received = '1' then case conv_integer(receivedByte) is -- 0-F - 0-3 bits when 0 to 15 => CodeDinA(3 downto 0) <= receivedByte(3 downto 0);

Теги: #python #компиляторы #FPGA #FPGA #FPGA #FPGA #forth #soft процессор

Вместе с данным постом часто просматривают:

Автор Статьи


Зарегистрирован: 2019-12-10 15:07:06
Баллов опыта: 0
Всего постов на сайте: 0
Всего комментарий на сайте: 0
Dima Manisha

Dima Manisha

Эксперт Wmlog. Профессиональный веб-мастер, SEO-специалист, дизайнер, маркетолог и интернет-предприниматель.