Проектирование конфигурируемых процессоров на базе ПЛИС

Окончание. Начало в № 2,3 '2006,

Проектирование конфигурируемых

процессоров на базе ПЛИС

Илья ТАРАСОВ, к. т. н.

tile@kc.ru

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

ПЛИС и архитектура системы

Эффективность реализуемых процессоров и систем на кристалле в большой степени зависит от выбранной элементной базы. Как в пределах продукции одного производителя, так и при переходе между различными фирмами может оказаться, что производительность и аппаратные ресурсы, необходимые для проекта, будут различаться (и иногда очень существенно). Решения, хорошо зарекомендовавшие себя в мире ASIC, не всегда столь же эффективны при их применении в ПЛИС. Напротив, программируемая аппаратная платформа позволяет в короткие сроки реализовывать решения ad hoc, которые при прочих условиях оказались бы совершенно неоправданными из соображений экономической эффективности. Принимая во внимание все возрастающую стоимость технологической подготовки производства ASIC, можно понять, что разрабатываемые ASIC-процессоры должны иметь достаточно универсальные возможности и широкую сферу применения, чтобы их разработка и производство окупились. Введение на кристалл специализированных устройств приемлемо постольку, поскольку эти устройства могут быть востребованы в изделиях с достаточно большим объемом выпуска. В то же время ПЛИС совершенно не требуют, чтобы реализуемое в них цифровое устройство обладало универсальными характеристиками и было пригодно для использования в целом ряде проектов. Если разработка софт-процессора окажется достаточно дешевой, то с ним можно будет согласовать некоторое количество специализированных устройств, способных за счет своей специализации значительно повысить общую производительность проекта по сравнению с универсальными процессорными

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

При решении этого вопроса необходимо иметь в виду, что гибкость ПЛИС не только позволяет реализовать самые разные цифровые схемы, но и открывает дорогу для реализации схем, крайне неэффективных на данной аппаратной базе. Анализируя характеристики существующих софт-процессоров, можно заметить, что некоторые их показатели напрямую основаны на особенностях архитектуры ПЛИС. Например, софт-процессор Nios фирмы Altera имеет 256 регистров, что наводит на мысль об их размещении в блоке M4K. В то же время процессор MicroBlaze содержит 32 регистра общего назначения, поскольку ПЛИС Xilinx допускают конфигурирование логических ячеек

в качестве памяти с организацией 16x1. Поэтому для ПЛИС ХШпх оказывается эффективной организация регистров в виде блоков с числом, кратным 16. Можно привести и другие примеры того, как особенности аппаратного состава ПЛИС влияют на эффективность тех или иных схемотехнических решений. Рассмотрим, как именно возможности ПЛИС соотносятся с потребностями процессоров.

Распределение ресурсов ПЛИС для реализации отдельных узлов процессора

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

Данную таблицу можно прокомментировать. Во-первых, она разделена на две группы

Таблица. Типы памяти, доступные в составе ПЛИС и подключаемых к ней внешних устройств

Тип Триггеры Распределенная Блочная Статическое ОЗУ, NOR флэш Динамическое ОЗУ, №№ флэш

Тактовая частота 200-500 150+ 150+ 10-100-200 100,133,166,200

Задержка при доступе, тактов 0 0-1 0-1 0-2 До 10

Объем До 100 байт 1-16 кб (до 1 Мб) 4-64 кб (до 1 Мб) 64-256 кб 32 Мб и более

Размещение Ячейки ПЛИС Ячейки ПЛИС (только Xilinx) Выделенные блоки ПЛИС Внешняя микросхема Внешняя микросхема или модуль DRAM

Регистры + - -

Код - + -

Данные - + +

Стек + + -

I I Устройство расположено на кристалле ПЛИС I I Внешняя микросхема

I I Плохой показатель I I Применение требует дополнительного внимания

I I Хороший показатель

+ Рекомендуется применение в этом качестве

— Крайне не рекомендуется применение в этом качестве

? Применение возможно в зависимости от обстоятельств

колонок, которые представляют устройства, расположенные на кристалле, и внешние микросхемы. Очевидно, что характеристики внешних микросхем могут быть самыми разными, но в таблице приводятся сведения о типичных вариантах, реализуемых без существенных усилий, и необходимости решения сложных технических проблем. Вместе со статической памятью рассматривается NOR-флэш, а с динамической — NAND-флэш. Это сделано потому, что, несмотря на совершенно разное назначение, такие разновидности памяти имеют схожий электрический интерфейс и временные диаграммы работы. Первая группа устройств характеризуется относительно быстрым обращением к произвольной ячейке памяти, осуществляемым или асинхронно, или за небольшое число тактов. Статическое ОЗУ или флэш-память с асинхронным интерфейсом допускают чтение данных в том же цикле работы — после выставления нужного адреса данные на выходе появляются с некоторой задержкой и не требуют ожидания фронта тактового сигнала (у микросхем с асинхронным интерфейсом такой вход отсутствует). Внешняя простота работы компенсируется большим временем задержки, чем у устройств с синхронным интерфейсом: типичное время доступа ОЗУ составляет 10-12-15 нс, а для флэш-памяти характерны значения 55, 70, 90 и 120 нс. Статические ОЗУ с синхронным интерфейсом позволяют работать с частотами до 200 МГц (что соответствует периоду тактового сигнала 5 нс), но имеют более сложные временные диаграммы и выставляют данные после нескольких периодов тактового сигнала относительно прихода нужного адреса. Еще более сложный алгоритм доступа предполагают динамические ОЗУ и флэш-память с организацией NAND. Такие устройства оптимизированы для эффективного выполнения блочных операций, а доступ к произвольной ячейке может потребовать довольно значительного числа тактов (которое существенно варьируется в пределах всего многообразия устройств динамического ОЗУ).

Применение статического и динамического ОЗУ различается не только по алгоритму доступа к этим типам памяти, но и по минимально допустимым частотам работы по указанным интерфейсам. Устройства динамического ОЗУ имеют нижнюю границу тактовой частоты. Большие значения частоты (например, 83 МГц для некоторых SDRAM) могут оказаться неприемлемыми для отдельных семейств ПЛИС, поскольку те не смогут обеспечить стабильную работу проекта. А потому динамическая память должна использоваться достаточно осторожно, с пониманием того, что реальная производительность при произвольном доступе может оказаться ниже, чем для статической памяти с формально меньшей тактовой частотой.

Итак, рассмотрим таблицу «по вертикали». В первой колонке расположены триггеры

логических ячеек ПЛИС, представляющие собой самый быстрый и дефицитный программируемый ресурс. Именно благодаря триггерам можно достичь очень высоких тактовых частот, к тому же все регистровые устройства (в том числе и регистры процессора) реализуются в них крайне удобно. Существенным недостатком является то, что в каждой логической секции ПЛИС расположен только один триггер. Следовательно, при слишком активном их использовании ресурсы ПЛИС исчерпаются очень скоро, а проект будет крайне «однобоким» (поскольку множество других программируемых ресурсов окажутся просто незадействованными). В ПЛИС начального уровня имеется несколько тысяч триггеров, поэтому в таблице указана цифра «до 100 байт». Сочетание такого маленького объема с крайне высокой скоростью позволяет сделать вывод о том, что весьма удобно на базе триггеров реализовать регистры процессора. При небольшой глубине стека можно использовать регистры для хранения нескольких адресов вызова, но эффективность такого решения зависит от многих факторов, соответственно, в таблице оно показано со знаком вопроса. Прочие применения (хранение кода или данных) — крайнее, совершенно не оправданное расточительство.

Следующий ресурс ПЛИС — распределенная память логических ячеек (правда, кристаллы Altera такую возможность не предоставляют). В действительности эта память является фрагментом конфигурационного ОЗУ самой ПЛИС, в которой хранятся в том числе и таблицы истинности логических генераторов. В каждой секции ПЛИС, кроме триггера, имеется 4-входовый логический генератор, который программируется путем занесения в него таблицы истинности. Для 4 входов требуется описать 16 возможных состояний, то есть использовать память 16x1, а путем введения небольшого количества дополнительных соединений эта память становится доступной разработчику. Таким образом, на каждый триггер приходится 16 бит памяти, организованной, правда, единственным образом — 16x1. Память обладает достаточно высоким быстродействием и в принципе может объединяться для образования более крупных блоков. Однако на практике при организации крупных блоков возникают проблемы — для соединения мелких фрагментов ОЗУ требуется слишком много трассировочных линий, трассировка становится запутанной, и в ПЛИС возрастают задержки распространения сигналов. Поэтому блоки на базе памяти желательно делать небольшого объема, и почти идеальным вариантом является стек. Регистры процессора в этом отношении хуже, поскольку у распределенной памяти может быть максимум два порта. В каждом такте работы такого модуля можно обращаться к произвольным регистрам, но только к каким-то определенным (максимум двум). Для стека это приемлемый

порядок работы, для регистров же — предмет особого рассмотрения. Наконец, в таблице знаком вопроса помечен пункт «Данные». Действительно, мелкие блоки данных также реализуются с помощью распределенной памяти. Это может быть как память общего назначения (для хранения переменных программы), так и буфер для обмена с внешним устройством. Хорошим примером служит организация вспомогательного программируемого автомата для вывода на LCD — современные LCD имеют достаточно медленный интерфейс, поэтому в качестве буферного элемента используется двухпортовая распределенная память. Процессор записывает символы по первому порту, а второй управляющий автомат (или процессор) считывает их по другому, обновляя данные на дисплее с соблюдением требуемых временных характеристик. Для дисплея 16x2 символа распределенная память прекрасно подходит по объему (требуется 16x2x8=256 байт; для триггеров этого чересчур много, а для блочной памяти — слишком мало).

Следующий ресурс (последний среди на-кристальных) — блочная память. Следует отметить, что на протяжении последних нескольких лет блочная память ПЛИС эволюционировала очень бурно, и в первую очередь это относится к ее объему. Например, ПЛИС начального уровня Spartan-3 с 200 тыс. эквивалентных вентилей имеет 12 встроенных блоков, каждый из них представляет собой двухпортовая память с организацией 1Kx18. Надо сказать, что с учетом возможного достижения высокой плотности кода это достаточно большой объем. В силу своей специфики (относительно крупные блоки, удобный интерфейс, высокая производительность) такая память подходит практически для любых применений, исключая, возможно, регистры. Действительно, даже для устаревших 4-килобитных блоков каждый блок памяти способен хранить 128 32-разрядных регистров, обеспечивая на каждом такте доступ к двум из них. Для памяти 1Kx18 таких регистров получается уже 512, что выглядит несколько избыточно. В то же время для хранения программы 12 блоков памяти являются скорее средним, если не низким показателем (современные микроконтроллеры предоставляют в распоряжение разработчика 32, 64 и даже 256 кбайт памяти программ, расположенной на кристалле). А значит, оптимальное применение блочной памяти — это хранение программы и, вероятно, небольшого количества данных.

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

Итак, статическая память появляется в системе тогда, когда ресурсов самой ПЛИС явно не хватает. Ее объем в целом больше, чем у накристальной памяти ПЛИС, но вот время доступа (не в тактах, а в наносекундах) уже существенно выше. Главный момент, который возникает в этом случае, — линии интерфейса необходимо расположить вне кристалла, соединив выводы ПЛИС с сигнальными выводами памяти. Проект «выпадает из поля зрения» САПР, сигналы распространяются уже не только по кристаллу ПЛИС, где можно учесть многие факторы и добиться частот до 100 МГц, а частично уже и по внешним печатным проводникам. Поэтому в таблице практически везде поставлены знаки вопроса — внешняя память не имеет каких-либо особенных недостатков. Исключая разве что тот факт, что регистры размещать в ней совершенно нецелесообразно — для этого есть гораздо более быстрые программируемые ресурсы ПЛИС, которые прекрасно подходят для реализации небольших объемов памяти. Во внешней же памяти можно поместить как данные, так и код. Немодифицируемые записи (код, таблицы констант) могут быть размещены и во флэш-памяти.

Наконец, динамическая память располагает исключительно большими объемами (стандартные модули SDR/DDR имеют объем 256, 512, 1024 Мбайт), но требует к себе повышенного внимания. Причем внимание необходимо уделить сразу двум моментам: проектированию контроллера такой памяти, размещаемого в ПЛИС (это не совсем тривиальная задача), и печатной плате, способной обеспечить целостность сигналов на частотах в районе 100 МГц. Подобные решения для HDL существуют (например, в свободно распространяемой утилите Memory Interface Generator, доступной для загрузки с w ww .xilinx.c om), но трассировка печатной платы для динамической памяти (и особенно для модулей) весьма ответственная задача. Важно то, что доступ к произвольной ячейке может потребовать больше одного такта, поэтому основное использование динамической памяти — хранение больших объемов данных, не требующих гарантированного времени доступа к произвольной ячейке.

Варианты процессорных систем на базе ПЛИС

1) «Система на кристалле»

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

2) «Контроллер»

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

3) «Компьютер»

Дальнейшее наращивание функциональности всей платы позволяет получить систему «компьютерного» класса. В этом случае внешние микросхемы находят применение и для хранения кода, и для хранения данных. Блочная память ПЛИС может быть использована разными способами — например, в качестве кэша или как независимый фрагмент кода, расположенный в том же адресном пространстве, что и одна из внешних микросхем (или обе: например, часть блочной памяти может хранить наиболее часто используемые блоки кода, а часть — важнейшие системные переменные). Память, исчисляемая мегабайтами, позволяет реализовать полноценную вычислительную систему, поддерживающую богатый набор периферийных устройств.

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

Регистровые модели процессоров

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

Данная архитектура предусматривает реализацию некоторого количества равноправных («симметричных») регистров. Все арифметические и логические операции, а также операции пересылки могут выполняться над

Симметричная архитектура

N2 возможных комбинаций операндов

Рис. 1. Симметричная регистровая архитектура

любым набором операндов. Обозначив число регистров как N, можно увидеть, что для операции над двумя регистрами возможны N2 сочетаний операндов. Возможность использования любой пары регистров для выполнения вычислений позволяет, в свою очередь, размещать данные в произвольном регистре, что облегчает разработку эффективного компилятора для такого процессора. С другой стороны, если для обозначения номера одного регистра требуется log2N разрядов поля команды, то для обозначения двух — соответственно 2log2N. Более того, регистр-получатель результата может не совпадать с одним из операндов, что потребует уже втрое большей ширины поля команды. В качестве примера можно привести архитектуру PowerPC, где при 32 регистрах возможна команда вида add r1, r2, r3. С учетом того, что на кодирование одного из 32 регистров требуется 5 разрядов поля команды, необходимо 15 разрядов только для указания номеров регистров, которые будут задействованы при выполнении текущей операции (имеются в виду, конечно, арифметические, логические и операции пересылки). В процессорах x86 также присутствуют черты симметричной архитектуры, поскольку из 4 регистров общего назначения (EAX, EBX, ECX, EDX) можно использовать любую пару для выполнения операций над двумя аргументами, но регистр-получатель результата обязательно совпадает с первым операндом. Это позволяет сократить разрядность поля команды, выделенного на указание регистров.

Одновременно, кроме равноправных регистров, в процессорах существуют регистры, для которых набор операций ограничен. Для x86 — это ESI, EDI, EBP, ESP сегментные регистры, регистры управления

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

В подавляющем большинстве асимметричных архитектур присутствует такой регистр, как аккумулятор. Это «универсальный» регистр, являющийся получателем результата арифметических и логических операций, служащий одним из операндов для пересылки в/из специальных регистров, а часто — и для организации обмена со всеми регистрами процессора. В последнем случае возможности пересылки данных между регистрами в точности соответствуют рис. 2 — во всех случаях данные загружаются в рабочие регистры только посредством аккумулятора. Подобный подход позволяет существенно сократить количество обрабатываемых кодов команд (то есть не ассемблерных мнемоник, а непосредственно комбинаций данных из памяти команд, обрабатываемых процессором), однако точно так же уменьшается и степень универсальности регистров. При этом основной причиной их специализации является добавление новых функций (для х86 примером таких функций становится использование регистра ЕСХ для хранения счетчика цикла с организацией декремента и перехода по команде JECXZ). Тот факт, что некоторые действия могут быть выполнены лишь с определенным регистром, не только уменьшает длину команды (в действительности такая «экономия» в некоторых случаях совершенно несущественна), но и упрощает механизм декодирования команды и уменьшает сложность управляющего устройства процессора. Если набор аргументов для каждой команды строго фиксирован, из цикла работы процессора можно исключить такт декодирования!

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

В качестве одного из вариантов «предельного приближения» к асимметричной архи-

Счетчик Стек данных инструкций

на ip

Указатель стека данных

—1 1

Указатель стека возвратов

Рис. 3. Стековая архитектура

тектуре рассмотрим стековую модель (рис. 3). Она подразумевает организацию всех регистров общего назначения в виде стека (структуры, работающей по принципу «первым вошел — последним вышел»). При этом стек возвратов отделен от стека данных, и оба стека имеют уникальные аппаратные указатели на вершину. Асимметрия состоит в том, что аргументом всех операций всякий раз являются верхние числа стека (или верхнее число, если требуется один аргумент). Аргументы, как правило, удаляются со стека, а результат помещается на вершину. Таким образом, каждая команда имеет только одну форму — безоперандную, поскольку каждый раз подразумевается, что операнды содержатся в верхних регистрах стека.

Недостаток стековой архитектуры — в наличии «бутылочного горлышка» в виде вершины стека, ограничивающей общую пропускную способность блока регистров. Кроме того, по сравнению с симметричным набором регистров, могут возникнуть проблемы в организации эффективного распределения данных по отдельным регистрам стека. Если для симметричной архитектуры есть возможность держать наиболее часто используемые данные в определенных регистрах и получать к ним доступ в любой момент, то для стековой архитектуры произвольный доступ к ячейкам, лежащим «внизу», как правило, не обеспечивается (хотя технически это выполнимо). А потому при возрастании числа операндов, активно применяемых в некотором фрагменте кода, стековые (и любые асимметричные) архитектуры все больше проигрывают симметричным. Однако такого же результата можно достичь при уменьшении количества обрабатываемых сочетаний команд, что повышает компактность кода. В итоге упрощается не только процесс формирования кода, но и внутренняя логика процессора, сложность соединений (что достаточно актуально для ПЛИС) и внутренние задержки. Кроме того, при неизменных алгоритмах увеличение числа регистров в симметричной архитектуре не приведет к значительному повышению производительности (например, при 15 часто используемых рабочих переменных переход от 16 к 32 регистрам

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

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

Повышение эффективности софт-процессоров

Вопросы создания эффективных процессорных архитектур и выбора программной модели достаточно сложны и обширны. Немыслимо сделать сколько-нибудь полный обзор данной области и однозначно указать современные тенденции в системной архитектуре и технических решениях микропроцессорных систем. Софт-процессоры также достаточно обширная область, а обсуждение подходов к их проектированию чем-то напоминает обсуждение вопроса «что можно нарисовать на холсте, имея кисть и набор красок?». У проектирования цифровых систем на базе ПЛИС есть нечто общее с живописью — имея «холст» в виде программируемого кристалла и «набор красок» в виде доступных для реализации цифровых узлов, можно реализовать широчайший набор систем даже в рамках одного «стиля живописи» (в данном случае — подкласса софт-процессоров). Поэтому необходимо сразу подчеркнуть, что упоминаемая далее информация никоим образом не может претендовать на полноту, а лишь демонстрирует частные подходы к повышению эффективности софт-процессоров в том виде, в котором они известны сегодня автору.

Совместное проектирование

программной и аппаратной части

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

вают в производительности и цене аналогичным микроконтроллерным решениям, естественно было бы воспользоваться возможностью создания уникальных специализированных решений для извлечения из ПЛИС максимальной выгоды. Главная точка приложения сил должна быть основана на следующем: некоторые технические и архитектурные решения не реализованы в микроконтроллерах исключительно по соображениям того, что они пригодятся малому числу потребителей. Для Л81С-устройств малый объем продаж почти автоматически означает чрезмерно высокую стоимость единичного экземпляра и, как следствие, некон-курентоспособность изделия. Поэтому слишком экзотические варианты набора регистров и периферийных устройств в мик-роконтроллерных системах не встречаются. Но нет ничего невозможного или нецелесообразного в реализации узкоспециализированных архитектур в ПЛИС, поскольку изменить такую архитектуру можно простым перепрограммированием устройства (а для FPGA на базе статической памяти предельного числа циклов перепрограммирования не существует). Следовательно, основной упор при использовании софт-процессоров следует делать на специализацию путем максимального приближения архитектуры процессора и его системы команд к потребностям решаемой задачи и особенностям выполняемых на этом процессоре программ.

В практике автора встречалась задача вычисления определителя 2x2 для 48-разрядных чисел. Для хранения промежуточного результата требовалось 96 разрядов, и все это вместе снижало эффективность 16- и 32-разрядных систем. Реализация в ПЛИС полноценного сопроцессора, способного работать с 96-разрядными числами, требовала достаточно большого количества логических ячеек. В то же время, рассматривая алгоритм, можно заметить, что вычисление определителя сводится к операции вида а*^Ь*с. Запишем эти вычисления в некотором абстрактном псевдокоде:

Итак, требуемый набор операций сводится к загрузкам аргументов в 2 из 3 рабочих регистров (при этом г0 и г1 могут иметь 48 разрядов, а 96 требуются только для г2), а также двум арифметическим командам — перемножению г0*г1 с занесением результата в г2, и тому же перемножению с вычитанием результата из предыдущего значения этого регистра. Очевидно, что весь набор стандартных арифметических и логических операций, а также разнообразные команды пересылки между регистрами попросту

не требуются для этой задачи. Сопроцессор, способный выполнять подобные вычисления, занял примерно 300 логических ячеек, и по сравнению с эмуляцией вычислений с 48- и 96-разрядными числами на 16- или 32-разрядном процессоре, выигрыш в производительности достигал 10-15 раз! При этом явно видно, что полученный сопроцессор является чрезмерно урезанным вариантом вычислительного устройства, фактически предназначенного для аппаратного ускорения од-ного-единственного алгоритма. Тем не менее, ввиду достаточно низкой трудоемкости создания такого сопроцессора, его применение оказалось вполне оправданным.

Упомянутый подход является простейшим примером большого направления, известного как hardware&software co-development (то есть совместное проектирование аппаратного и программного обеспечения). Инструменты синтеза аппаратуры, поддерживающей наиболее характерные алгоритмы, профилирования программного обеспечения и совместного моделирования все чаще появляются на рынке. Увеличение объемов ПЛИС не только позволяет реализовывать в них софт-процессоры, но и повышает их актуальность, поскольку для быстрого, эффективного и хорошо сопровождаемого проекта объемом в несколько миллионов эквивалентных вентилей требуется привлечение прикладных программистов и разработчиков системного уровня, хорошо знакомых со спецификой решаемой задачи. Таким специалистам гораздо удобнее вносить коррективы в программу на языке высокого уровня, чем в HDL-описание. Поэтому вполне можно предоставить в их распоряжение процессор, расположенный на кристалле и аппаратно поддерживающий наиболее важные для решаемой задачи алгоритмы.

Задачи цифровой обработки сигналов

Аппаратные умножители независимых операндов, работающие на высокой частоте, — одно из основных преимуществ современных ПЛИС. Даже микросхемы начального уровня легко могут обеспечить производительность в несколько миллиардов умножений с накоплением в секунду (например, весьма недорогая микросхема XC3S200 имеет 12 блоков умножения, каждый из которых способен работать на частоте свыше 200 МГц). Таким образом, цифровая фильтрация, или такие направления задачи, как нейросетевые вычисления, вейвлет-преобразование или генетические алгоритмы, могут быть эффективно распараллелены. А удельная стоимость их реализации в ПЛИС меньше, чем даже на современных сигнальных процессорах.

Цифровые фильтры в ПЛИС достаточно просто реализуются с помощью программного пакета System Generator, входящего в состав инструментария Xilinx. Однако может возникнуть и ситуация, при которой основой проекта окажутся оригинальные

устройства цифровой обработки, не поддерживаемые System Generator и, соответственно, проектируемые разработчиками на HDL. При достаточно большой производительности сама ПЛИС не обеспечивает удобного управления процессом обработки: может потребоваться изменение коэффициентов фильтров, останов, возобновление работы или сброс очереди данных одного из устройств, мониторинг состояния, выполнение некоторых действий по достижению определенных условий и т. п. Все эти операции довольно удобно выполняются в сигнальных процессорах, поскольку те предоставляют возможность программного управления ходом вычислений, позволяя описывать решаемую задачу на обычном алгоритмическом языке (что естественно для любого процессора). Однако в ПЛИС подобные изменения приходится вносить непосредственно в HDL-описание устройства, что приводит к повторной трансляции проекта и загрузки его в кристалл. В этой связи размещение в ПЛИС софт-процессора, который обеспечил бы интерфейс с устройствами цифровой обработки сигналов, резко сократит время на коррекцию алгоритмов работы устройства и позволит ограничиться прикладным программированием вместо постоянной коррекции конфигурации ПЛИС. Множественные адресные пространства и объединение памяти разных типов в одном адресном пространстве

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

Разделению адресных пространств способствует тот факт, что ПЛИС с помощью программируемых трассировочных ресурсов, имеющихся на кристалле в большом количестве, обеспечивает эффективный доступ к отдельным блокам внутренней памяти. Поэтому каждый блок памяти теоретически может располагаться в собственном адресном пространстве. Практическая польза от такого разделения видна на примере ввода данных из нескольких каналов скоростного АЦП во внутренний буфер ПЛИС. При размещении данных последовательно в одном и том же блоке памяти ввод данных из 4 каналов потребует 4 обращений к памяти (или соответствующего расшире-

mov r0, a mov r1, d r2 = r0*r1 mov r0, b mov r1, c r2=r2-r0*r1

ния ее шины данных). Или можно ввести в состав процессора SIMD-команду (Single Instruction — Multiple Data), которая в одном цикле примет данные одновременно из 4 каналов и запишет каждое из принятых чисел по одному и тому же адресу, но в индивидуальное адресное пространство. В конечном итоге в каждом из 4 блоков памяти окажется поток данных, принятый из соответствующего канала АЦП.

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

Существует и возможность назначать часто используемым или критичным к времени доступа устройствам уникальные адресные пространства. Например, доступ к АЦП на чтение данных может выполняться не командой чтения из порта с адресом N (требующей передачи номера порта в качестве параметра), а безоперандной командой «чтение АЦП», которая сформирует уникальный шинный цикл, копирующий данные с группы входов ПЛИС во внутренний регистр софт-процессора. Отсутствие операндов в команде означает как экономию места в дефицитной блочной памяти, так и сокращение времени на ее выполнение. Кроме того, та же команда может производить, например, инкремент регистра-указателя адреса или иные подобные действия, связанные с чтением данных АЦП. Разумеется, при большом количестве периферийных устройств вынести каждое из них в уникальное адресное пространство окажется невозможным, однако для целого ряда случаев можно предложить комбинированные решения (общее адресное пространство для периферийных устройств и выделенные пространства с безоперандными командами для наиболее часто используемых). Надо отметить, что широкому внедрению подобного подхода в микроконтроллеры мешает следующий факт: в разных сферах применения наиболее активно используемыми могут оказаться совершенно разные периферийные устройства.

Кроме разделения вполне возможно и объединение физически отдельных устройств в единое адресное пространство. Например, накристальная блочная память, используемая в качестве памяти кода, может быть расширена внешней микросхемой флэш-ПЗУ. Быстродействие этих устройств, очевидно,

различно: доступ к блочной памяти требует лишь одного такта (при 50-100 МГц тактовой частоты для таких ПЛИС, как 8раг!ап-3 и Virtex-4), тогда как медленная внешняя микросхема может потребовать до 100 нс, что составит 5-10 тактов при упомянутых частотах процессора. Соответственно, исходя из предпочтений разработчика, возможны как минимум следующие варианты:

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

2) Блочная память находится в младших адресах пространства памяти кода. Обращения к этим адресам формируют цикл доступа к блочной памяти ПЛИС (с 1 тактом задержки на получение команды). В этой памяти хранятся часто вызываемые системные процедуры и наиболее критичные к производительности фрагменты кода. При попадании адреса в диапазон, соответствующий флэш-ПЗУ, формируется шинный цикл с 5-10 тактами задержки.

3) В младших адресах находится флэш-ПЗУ, хранящая часть программного обеспечения, которая редко подвергается изменениям. Это позволяет реже проводить перепрограммирование флэш-ПЗУ в процессе отладки устройства. Блочная память находится в старших адресах и предназначена для хранения модулей программы, наиболее часто подвергающихся изменениям в процессе отладки.

Приведенные примеры не образуют сколько-нибудь исчерпывающего списка и приведены лишь в качестве иллюстрации возможностей, которые открывает гибкость ПЛИС. В действительности, при отладке проекта можно использовать последний из перечисленных вариантов, а в готовом устройстве — или «прозрачное» кэширование, или жестко фиксированный диапазон адресов для быстрой блочной памяти. Ничем не ограниченная перепрограммируемость ПЛИС (по крайней мере, FPGA на основе статической памяти) предлагает широчайшие возможности изменения архитектуры вычислительного комплекса на системном уровне.

Характеристики ПЛИС современных семейств и рекомендации к «быстрому старту»

Составить полноценное мнение о перспективах использования софт-процессоров в конкретной прикладной области очень сложно без самостоятельной реализации

таких процессоров. Несмотря на то, что проекты, выполняемые без тонкой настройки САПР и ограничений по взаимному расположению компонентов на кристалле ПЛИС, будут проигрывать промышленным софт-процессорам (в частности, 32-разрядный процессор, по функциональности аналогичный MicroBlaze, имеет частоту на 15-20% ниже), понимание процесса проектирования и возникающих при этом проблем поможет глубже понять особенности архитектуры промышленных систем и причины, по которым разработчики принимают то или иное техническое решение. Кроме того, выполняемая конкретным коллективом проблемная специализация собственного процессорного ядра может существенно повысить его эффективность в конкретной прикладной задаче, делая его более предпочтительным, чем MicroBlaze или даже ASIC.

Для «быстрого старта» настоятельно рекомендуется использовать современные семейства ПЛИС, обладающие не только расширенными возможностями, но и повышенной производительностью (в том числе и экстенсивно, за счет более современного техпроцесса). Ориентация на устаревшие семейства приведет скорее к разочарованию от невозможности реализовать систему с параметрами, актуальными сегодня. В частности, ПЛИС Spartan-3 обеспечат частоту 32-разрядного процессора, выполненного по схеме, представленной во второй части данной статьи, на уровне 50-60 МГц, тогда как от устройств Virtex-4 можно ожидать и 100-120 МГц. Устройства Xilinx выглядят предпочтительнее по сравнению с аналогичной продукцией Altera, поскольку наличие распределенной памяти делает возможной реализацию в этих блоках регистровых устройств «среднего» размера (16-32-64 регистра). Разумеется, это не исключает использования ПЛИС других фирм.

В нижней ценовой категории (чуть выше 100 у. е.) находятся такие продукты, как Spartan-3 Starter Kit, и недавно появившийся Spartan-3E Starter Kit. Последняя плата основана на ПЛИС Spartan-3E, и ее возможности намного шире (например, память DDR, LCD, АЦП, Ethernet, USB), что облегчает построение законченного устройства на базе софт-процессора. Наконец, можно обратиться к еще более мощным платам серии ML-40x, выполненным на основе ПЛИС Virtex-4. Отметим, что возможностей даже платы начального уровня (S3 Starter Kit) оказалось вполне достаточно для экспериментальной проверки идей, изложенных в данной статье, и построения нескольких вариантов 32-разрядного процессора.

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