12K подписчиков

Микроконтроллеры для начинающих. Часть 10. RISC и CISC - единство и борьба противоположностей

1,5K прочитали

Очередная статья цикла должна была более подробно рассказывать о процессоре и памяти PIC, так как в предыдущей я уделил внимание STM8. Но в процессе подготовки статьи я столкнулся с необходимостью все таки сначала рассказать еще о двух понятиях - RISC и CISC, которым хотел уделить внимание позже, во время рассказа о системах команд процессоров.

Без этого мне будет трудно рассказать вам, почему 8-битные PIC устроены именно так, сложно и не похоже на другие микроконтроллеры (во всяком случае, на первый взгляд). А включение рассказа о RISC в статью о PIC делает ее слишком большой и сложной. Да и сама эта тема общая, не связанная с конкретным семейством микроконтроллеров. Так и появилась эта статья.

Сегодня нам понадобятся знания, которые мы получили ранее из статей:

Кроме того, я буду иногда ссылаться на статью Микроконтроллеры для начинающих. Часть 9. Процессор и память в STM8

Что такое RISC и CISC

Эти аббревиатуры вы, скорее всего, уже встречали. RISС это Reduced Instruction Set Computer или, по русски, компьютер с усеченным набором команд. CISC это Complex Instruction Set Computer или, по русски компьютер с комплексным набором команд.

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

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

От простого к сложному

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

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

Но довольно скоро выяснилось, что ЭВМ могут успешно решать не только вычислительные задачи и началась гонка технологий. Производители ЭВМ, с одной стороны, выясняли запросы пользователей и старались их удовлетворять при разработке новых машин. А с другой, обращались в академические круги с запросом"а что еще ЭВМ могут"?

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

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

Анализируй это

Бурное развитие и ощущение "мы все можем" не отменяло анализа результатов реального применения ЭВМ. И вот тут выяснились интересные подробности. Оказалось, что большинство программ используют лишь малую часть доступных команд. При этом используемый набор команд различался для разных областей применения ЭВМ.

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

От сложного к простому

Было предложено исключить из системы команд ЭВМ редко используемые команды и упростить оставшиеся. Это позволит упростить схемотехнику и снизить стоимость ЭВМ, но позволит и повысить быстродействие.

Однако, RISC архитектура это не только сокращенный набор команд, как часто считается исходя из дословного понимания названия. Это подход к построению. ЭВМ в целом, включая и адресацию, и архитектуру памяти.

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

CISC

Наиболее известным современным представителем CISC подхода является архитектура процессоров 80x86 используемая в настольных ПК и ноутбуках. Это универсальные процессоры обладающие широчайшими возможностями в организации и управлении памятью, богатейшей системой команд, развитыми режимами адресации операндов.

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

Но цикл статей о микроконтроллерах, поэтому я ограничусь лишь таким вот, кратким, упоминанием об универсальных процессорах и CISC архитектуре.

RISC

А вот тут я буду рассматривать вопрос гораздо более подробно, так как подавляющее большинство 8-битных микроконтроллеров используют RISC архитектуру (да, и Гарвардскую, при этом).

И так, основная идея RISC подхода это упрощение. Сокращение количества доступных команд дает возможность уменьшить количество разрядов необходимых для указания кода операции. Сокращение количества операндов в команде позволяет еще больше уменьшить длину кода команды. Тот же эффект дает и исключение сложных режимов адресации. А значит, мы можем уменьшить разрядность шины данных памяти и сократить количество циклов для получения команды и данных.

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

Убираем лишние команды

Как я уже говорил, не все команды одинаково востребованы. Давайте более подробно разберем это на примере команд пересылки данных. Чаще всего команды пересылки данных имеют аббревиатуру MOV.

В процессорах 80х86 однако имеются не только команды пересылки данных общего назначения, но и специфичные для работы со строками. Я говорю о командах MOVS, LODS, STOS. От обычной команды MOV они, по большому счету, отличаются лишь использованием специальных регистров и автоматическим увеличением указателей, для команд MOVS. А LODS и STOS задают одним из операндов регистр аккумулятор.

Значит, эти команды можно без особого ущерба просто исключить и пользоваться универсальной MOV. Кстати, эти команды работы со строками действительно используются гораздо реже обычной команды пересылки.

У процессоров 80х86 есть отдельные команды для установки некоторых флагов состояния процессора, например, команда, STC для установки флага переноса. Мы можем исключить эту команду и использовать вместо нее универсальные команды установки/сброса заданного бита в байте/слове. Или пойти еще дальше и оставить только побитовые команды OR, AND, XOR.

Подобным образом можно сократить количество доступных команд очень сильно. Так в BaseLine PIC есть всего 33 команды, в MidRange 35 команд, в PIC18 порядка 70 команд. В STM8 есть порядка 80 команд. Это гораздо меньше, чем у 80х86.

Вводим аккумуляторную архитектуру и делаем команды одноадресными

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

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

Влияние изменений и сокращений в наборе команд на память программ

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

В качестве примера, далеко забегая вперед, я приведу формат команд для MidRange PIC

Формат команд процессора 8 битных PIC Microchip семейства MidRange
Формат команд процессора 8 битных PIC Microchip семейства MidRange

Нас в данной иллюстрации интересует лишь поле OPCODE и общее количество бит занимаемое командами. А общая длина команды всего 14 бит (для BaseLine 12 бит). При этом поле операции занимает 3, 4 или 6 разрядов. То есть, менее байта.

И для считывания полной команды из памяти программ нам нужна 14-битная шина данных. Рассказ о памяти PIC еще впереди, но результаты оптимизации и использования RISC подхода у Microchip впечатляют. Менее двух байт на команду! У AVR Atmel команды занимают 2 байта, а у STM8 до 5 байт.

Внимательный читатель может заметить, "но позвольте, ведь мы теперь не всегда можем обойтись одной командой, мы иногда вынуждены использовать несколько команд для получения нужного результата, а значит, требуемый объем памяти будет больше и вся эта экономия ничего не даст!"

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

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

Исключение сложных методов адресации

Это следующих этап оптимизации, который влияет не только (и не столько) на длину команды, но и на время ее выполнения и на сложность аппаратуры процессора.

Давайте вспомним косвенную индексную адресацию в STM8 из предыдущей статьи

Косвенная индексная адресация в STM8 из 9 статьи цикла. Иллюстрация моя
Косвенная индексная адресация в STM8 из 9 статьи цикла. Иллюстрация моя

Что бы получить собственно данные нам нужно:

  1. Загрузить в процессор содержимое ячейки, адрес которой задан косвенной частью адресации операнда. В данном случае это ячейка с адресом strtbl+2
  2. Сложить полученное значение и содержимое индексного регистра (индексная часть адресации операнда)
  3. Загрузить в процессор собственно обрабатываемые командой данные из ячейки памяти с адресом полученным на шаге 2

Такая вот многоэтапная процедура. Да, она дает большую гибкость, но всегда ли такая гибкость нужна? На помощь опять приходит статистика реального использования доступа к данным в реальных программах.

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

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

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

Более гибкая и простая адресация в командах перехода

Программа должна иметь возможность передать управление в любую доступную точку памяти программ. Этот постулат сомнению не подвергается.

Но упрямая статистика на основании реальных программ свидетельствует, что большинство переходов выполняются в пределах ограниченного пространства памяти данных. Речь идет о командах условных переходов, которых в любой программе больше всего.

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

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

Итоговый результат оптимизаций и сокращений

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

Аналогичный результат, но уже для работы с памятью данных, дает исключение сложных режимов адресации. Конечно, в разных микроконтроллерах применены разные решения. И результаты отличаются. Так для 8-разрядных PIC большинство команд выполняются за 1 машинный цикл (4 такта) и занимают менее 2 байт памяти. Я не говорю сейчас о PIC18. Для STM8 команда может занимать до 5 байт, а сами команды выполняются за разное количество циклов. Но там и набор команд и способов адресации не такой уж и сокращенный.

Заключение

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

И CISC и RISC архитектуры имеют право на жизнь. Нельзя сказать, какая из них однозначно лучше, а какая хуже. Все зависит от конкретной ситуации. Причем RISC архитектура применяется не только в микроконтроллерах, но и в других процессорах. Примером могут служить Sun SPARK.

А вот теперь мы готовы приступить к более подробному рассмотрению микроконтроллеров PIC, как это сделано в предыдущей статье для STM8.

До новых встреч!