Собственный софт-процессор на ПЛИС с компилятором языка высокого уровня или Песня Мышки - опыт адаптации компилятора языка высокого уровня к многоядерному процессорному ядру.
Распространенной проблемой программных процессоров является отсутствие средств разработки для них, особенно если их набор инструкций не является подмножеством инструкций одного из популярных процессорных ядер.
В этом случае разработчики будут вынуждены решить эту проблему.
Прямое решение — создать компилятор языка ассемблера.
Однако в современных реалиях не всегда удобно работать в сборке, так как в ходе разработки проекта система команд может меняться из-за, например, изменившихся требований.
Поэтому задача простой реализации компилятора языка высокого уровня (HL) для программного процессора является актуальной.
Компилятор языка Python - Уж представляется простым и удобным инструментом разработки программного обеспечения для программных процессоров.
Инструментарий для определения примитивов и макросов как функций целевого языка позволяет реализовать критические места в ассемблере процессора.
В данной статье рассмотрены основные моменты адаптации компилятора для процессоров стековой архитектуры.
Вместо эпиграфа: Если взрослая мышь Возьми его и, бережно держа, Набейте его иголками Вы получите ёжика.
Если этот ежик Я заткнул нос, чтобы не мог дышать, Где-нибудь поглубже, бросьте его в реку У вас получится ерш.
Если этот ерш, С головой в тисках, Потяни за хвост сильнее Вы получите змею.
Если это правда, Подготовив два ножа.
Однако он, вероятно, умрет Но идея хорошая!
Введение
Во многих случаях при внедрении средств измерений и исследовательского оборудования предпочтительно использовать реконфигурируемые решения на базе ПЛИС/ПЛИС в качестве основного ядра системы.Такой подход имеет множество преимуществ, благодаря возможности легко и быстро вносить изменения в логику работы, а также за счет аппаратного ускорения операций обработки данных и сигналов управления.
Для широкого спектра задач, таких как цифровая обработка сигналов, встроенные системы управления, системы сбора и анализа данных, хорошо зарекомендовавшим себя подходом является объединение в одном решении блоков, реализуемых логикой ПЛИС для критических процессов, и программных элементов управления на базе одного или нескольких несколько программных процессоров для общего управления и координации, а также для реализации взаимодействия с пользователем или внешними устройствами/узлами.
Использование программных процессоров в этом случае позволяет несколько сократить время, затрачиваемое на отладку и проверку алгоритмов управления системой или алгоритмов взаимодействия отдельных узлов.
Типичные «списки желаний»
Часто в этом случае от программных процессоров не требуется сверхвысокая производительность (поскольку ее проще достичь за счет использования логических и аппаратных ресурсов ПЛИС).Они могут быть достаточно простыми (а с точки зрения современных микроконтроллеров - почти примитивными), поскольку могут обходиться без сложной системы прерываний, работать только с определенными узлами или интерфейсами и нет необходимости поддерживать ту или иную систему команд. .
Их может быть много, и каждый из них может выполнять только определенный набор алгоритмов или подпрограмм.
Ширина программных процессоров также может быть любой, в том числе не кратной байту, в зависимости от требований текущей задачи.
Типичными целями программных процессоров являются:
- достаточная функциональность системы команд, возможно, оптимизированная под поставленную задачу;
- высокая плотность программного кода, поскольку это позволит сэкономить ресурсы памяти ПЛИС;
- компактность — не хотелось бы, чтобы вспомогательные элементы занимали дефицитные ресурсы программируемой логики.
В этом случае разработчики будут вынуждены решить эту проблему.
Ее прямое решение — создать компилятор языка Ассемблера для программного процессора.
Однако в современных реалиях не всегда удобно работать в сборке, особенно если в ходе разработки проекта система команд будет меняться из-за, например, изменившихся требований.
Поэтому к перечисленным выше требованиям логично добавить требование простой реализации компилятора языка высокого уровня (HL) для программного процессора.
Исходные компоненты
Этим требованиям стековые процессоры отвечают с высоким процентом соответствия, поскольку нет необходимости обращаться к регистрам; ширина команды может быть небольшой.Объем данных для них может варьироваться и не привязан к емкости системы команд. Являясь де-факто (хотя и с небольшими оговорками) аппаратной реализацией промежуточного представления программного кода при компиляции (виртуальная стековая машина, или в терминах контекстно-свободных грамматик - машина хранения), позволяет транслировать грамматику любого языка в исполняемый код с низкими трудозатратами.
Кроме того, язык Форт является практически «родным» языком для стековых процессоров.
Трудозатраты на реализацию Форт-компилятора для стекового процессора сопоставимы с затратами на Ассемблер, с гораздо большей гибкостью и эффективностью реализации программ в будущем.
Имея задачу построить систему сбора данных с интеллектуальных датчиков в режиме, близком к реальному времени, был использован процессор Форт, описанный в работах [ 1 ] (в дальнейшем его иногда будут называть процессором whiteTiger по нику его автора).
Его основные особенности:
- отдельные стеки данных и возврата;
- Гарвардская архитектура организации памяти (отдельная память программ и данных, включая адресное пространство);
- расширение периферийными устройствами с использованием простой параллельной шины.
- Процессор не использует конвейер; выполнение команды двухтактное:
- получение инструкций и операндов;
- выполнение команды и сохранение результата.
Учитывая конфигурацию блочной памяти в ПЛИС, ширина команды установлена равной 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) с содержимым:
, где abc.py — имя файла с программой для программного процессора.c.py C:\D\My_Docs\Documents\uzh-master\tests\abc.py
Змея, кусающая себя за хвост или скрежетающая аппаратным и программным обеспечением
Для адаптации Ужа к процессору whiteTiger потребуются некоторые изменения, а также придется немного подкорректировать сам процессор.К счастью, в компиляторе не так много мест, которые нужно корректировать.
Основные «аппаратно-зависимые» файлы:
- asm.py — ассемблер и генерация чисел (литералов);
- gen.py — правила генерации низкоуровневого кода (функции, переменные, переходы и условия);
- stream.py – генерация потока загрузки;
- macro.py — определения макросов, по сути — расширения базового языка с аппаратно-специфичными функциями.
Алгоритм работы загрузчика прост, но проверен и надежен:
- при получении определенного управляющего байта загрузчик устанавливает активный уровень на внутренней линии сброса процессора;
- вторая байтовая команда сбрасывает счетчик адреса памяти;
- Далее следует последовательность тетрад передаваемого слова, начиная с младшего, объединенного с номером тетрады;
- после каждого байта с упакованной тетрадой идет пара управляющих байтов, первый из которых устанавливает активный уровень на линии разрешения записи в память, второй его сбрасывает;
- По завершении последовательности упакованных тетрад управляющий байт удаляет активный уровень на линии сброса.
Поскольку память данных участвует в логике работы ядра процессора, необходимо мультиплексировать ее линии данных и управления.
Для этого вводятся дополнительные сигналы 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 процессор
-
Что Я Могу Сделать С Моим Internet Explorer?
19 Oct, 24 -
Пост О Том, Как Я Лепила Игру Из Пластилина.
19 Oct, 24 -
Mvcc В Postgresql-8. Замораживание
19 Oct, 24 -
Как Поживает Open Xml?
19 Oct, 24 -
Зарабатывайте Деньги Дважды
19 Oct, 24