Как работает процессор на физическом уровне: интерактивный урок для начинающих / Хабр
интерактивный урок для начинающих / Хабр
Simple CPU — маленький урок, который знакомит новичка с ключевыми понятиями информатики. Хотя урок далеко не полный и предназначен для «самых маленьких», но даже образованному человеку приятно видеть, насколько доступно и элегантно можно изложить сложный материал.
Урок состоит из 8 интерактивных примеров.
1. Бинарное счисление.
2. Логические операции на примере штриха Шеффера (NAND gate).
Штрих Шеффера (NAND gate)
3. Триггер. Демонстрирует, как хранится информация в компьютере. Верхний переключатель изменяет значение бита, а нижний включает/отключает хранение.
D-триггер (триггер задержки)
Восемь триггеров сохраняют 1 байт информации.
4. Логические операции AND, OR, XOR. Щёлкая мышкой по входящим значениям, можно наглядно посмотреть, как они работают.
Что делать с числами, которые мы храним в памяти?
5. На схеме показано устройство под названием сумматор, которое складывает два бита. Если нужно сложить несколько бит, то последовательно используется несколько сумматоров: вход одного (carry in) подключается к выходу другого (carry out).
Опять же, это интерактивная схема.
Далее, как из калькулятора сделать компьютер?
6. Программирование.
С точки зрения CPU, программа не отличается от данных в том смысле, что здесь такой же двоичный код. Но он воспринимаются как инструкции. Например:
Инструкция | Код | |
«Добавить одно число к другому» | 00000001 | |
«Вычесть одно число из другого» | 00000010 |
У каждого байта в памяти есть свой адрес, так что мы можем обратиться к CPU и попросить сделать что-то с конкретным байтом. Например, если нужно обратиться к ячейке памяти № 5, то мы указываем её адрес 00000101.
Таким образом, команда «Сложить число в ячейке памяти № 5 с числом в ячейке памяти № 7 транслируется в машинный код:
00000001 00000101 00000111
(сложить)(адрес № 5)(адрес № 7)
7. Набор инструкций CPU.
8. Эмулятор CPU.
Здесь автор предлагает поиграться с простым эмулятором процессора, указывая инструкции в отдельных ячейках памяти. При этом инструкции меняют значение других ячеек, где тоже хранятся инструкции. Можно придумать забавные рекурсии. Компьютер понимает три инструкции: сложение, вычитание и перемещение данных из одной ячейки в другую.
Simple CPU на Github
Об автореP.S. Интересно, что проект родился на форумах Reddit, а его автор — только что закончивший школу пользователь r00nk. Поскольку r00nk двоечник, его сейчас не берут ни в один хороший колледж, так что он пытается пройти курс информатики самостоятельно, попутно изучая OpenGL.
Как работает процессор компьютера? | Losst
Процессор — это, без сомнения, главный компонент любого компьютера. Именно этот небольшой кусочек кремния, размером в несколько десятков миллиметров выполняет все те сложные задачи, которые вы ставите перед своим компьютером. Здесь выполняется операционная система, а также все программы. Но как все это работает? Этот вопрос мы попытаемся разобрать в нашей сегодняшней статье.
Процессор управляет данными на вашем компьютере и выполняют миллионы инструкций в секунду. И под словом процессор, я подразумеваю именно то, что оно на самом деле означает — небольшой чип из кремния, который фактически выполняет все операции на компьютере. Перед тем как перейти к рассмотрению как работает процессор, нужно сначала подробно рассмотреть что это такое и из чего он состоит.
Содержание статьи:
Что такое процессор или CPU?
Сначала давайте рассмотрим что такое процессор. CPU или central processing unit (центральное обрабатывающее устройство) — который представляет из себя микросхему с огромным количеством транзисторов, сделанную на кристалле кремния. Первый в мире процессор был разработан корпорацией Intel в 1971 году. Все началось с модели Intel 4004. Он умел выполнять только вычислительные операции и мог обрабатывать только 4 байта данных. Следующая модель вышла в 1974 году — Intel 8080 и мог обрабатывать уже 8 бит информации. Дальше были 80286, 80386, 80486. Именно от этих процессоров произошло название архитектуры.
Тактовая частота процессора 8088 была 5 МГц, а количество операций в секунду только 330 000 что намного меньше чем в современных процессоров. Современные устройства имеют частоту до 10 ГГц и несколько миллионов операций в секунду.
Мы не будем рассматривать транзисторы, переместимся на уровень выше. Каждый процессор состоит из таких компонентов:
- Ядро — здесь выполняется вся обработка информации и математические операции, ядер может быть несколько;
- Дешифратор команд — этот компонент относится к ядру, он преобразует программные команды в набор сигналов, которые будут выполнять транзисторы ядра;
- Кэш — область сверхбыстрой памяти, небольшого объема, в которой хранятся данные, прочитанные из ОЗУ;
- Регистры — это очень быстрые ячейки памяти, в которых хранятся сейчас обрабатываемые данные. Их есть всего несколько и они имеют ограниченный размер — 8, 16 или 32 бит именно от этот зависит разрядность процессора;
- Сопроцессор — отдельное ядро, которое оптимизировано только для выполнения определенных операций, например, обработки видео или шифрования данных;
- Адресная шина — для связи со всеми, подключенными к материнской плате устройствами, может иметь ширину 8, 16 или 32 бит;
- Шина данных — для связи с оперативной памятью. С помощью нее процессор может записывать данные в память или читать их оттуда. Шина памяти может быть 8, 16 и 32 бит, это количество данных, которое можно передать за один раз;
- Шина синхронизации — позволяет контролировать частоту процессора и такты работы;
- Шина перезапуска — для обнуления состояния процессора;
Главным компонентом можно считать ядро или вычислительное-арифметическое устройство, а также регистры процессора. Все остальное помогает работать этим двум компонентам. Давайте рассмотрим какими бывают регистры и какое у них предназначение.
- Регистры A, B, C — предназначены для хранения данных во время обработки, да, их только три, но этого вполне достаточно;
- EIP — содержит адрес следующей инструкции программы в оперативной памяти;
- ESP — адрес данных в оперативной памяти;
- Z — содержит результат последней операции сравнения;
Конечно, это далеко не все регистры памяти, но эти самые главные и ими больше всего пользуется процессор во время выполнения программ. Ну а теперь, когда вы знаете из чего состоит процессор, можно рассмотреть как он работает.
Как работает процессор компьютера?
Вычислительное ядро процессора может выполнять только математические операции, операции сравнения и перемещение данных между ячейками и оперативной памятью, но этого вполне достаточно, чтобы вы могли играть игры, смотреть фильмы и просматривать веб-страницы и многое другое.
Фактически любая программа состоит из таких команд: переместить, сложить, умножить, делить, разница и перейти к инструкции если выполняется условие сравнения. Конечно, это далеко не все команды, есть другие, которые объединяют между собой уже перечисленные или упрощают их использование.
Все перемещения данных выполняются с помощью инструкции перемещения (mov), эта инструкция перемещает данные между ячейками регистров, между регистрами и оперативной памятью, между памятью и жестким диском. Для арифметических операций есть специальные инструкции. А инструкции перехода нужны для выполнения условий, например, проверить значение регистра A и если оно не равно нулю, то перейти к инструкции по нужному адресу. Также с помощью инструкций перехода можно создавать циклы.
Все это очень хорошо, но как же все эти компоненты взаимодействуют между собой? И как транзисторы понимают инструкции? Работой всего процессора управляет дешифратор инструкций. Он заставляет каждый компонент делать то, что ему положено. Давайте рассмотрим что происходит когда нужно выполнить программу.
На первом этапе дешифратор загружает адрес первой инструкции программы в памяти в регистр следующей инструкции EIP, для этого он активирует канал чтения и открывает транзистор-защелку чтобы пустить данные в регистр EIP.
Во втором тактовом цикле дешифратор инструкций преобразует команду в набор сигналов для транзисторов вычислительного ядра, которые выполняют ее и записывают результат в один из регистров, например, С.
На третьем цикле дешифратор увеличивает адрес следующей команды на единицу, так, чтобы он указывал на следующую инструкцию в памяти. Далее, дешифратор переходит к загрузке следующей команды и так до окончания программы.
Каждая инструкция уже закодирована последовательностью транзисторов, и преобразованная в сигналы, она вызывает физические изменения в процессоре, например, изменению положения защелки, которая позволяет записать данные в ячейку памяти и так далее. На выполнение разных команд нужно разное количество тактов, например, для одной команды может понадобиться 5 тактов, а для другой, более сложной до 20. Но все это еще зависит от количества транзисторов в самом процессоре.
Ну с этим все понятно, но это все будет работать только если выполняется одна программа, а если их несколько и все одновременно. Можно предположить, что у процессора есть несколько ядер, и тогда на каждом ядре выполняется отдельная программ. Но нет, на самом деле там таких ограничений нет.
В один определенный момент может выполняться только одна программа. Все процессорное время разделено между всеми запущенными программами, каждая программа выполняется несколько тактов, затем процессор передается другой программе, а все содержимое регистров сохраняется в оперативную память. Когда управление возвращается этой программе, то в регистры грузятся ранее сохраненные значения.
Выводы
Вот и все, в этой статье мы рассмотрели как работает процессор компьютера, что такое процессор и из чего он состоит. Возможно, это немного сложно, но мы рассмотрели все более просто. Надеюсь, теперь вам стало более ясно то, как работает это очень сложное устройство.
На завершение видео об истории создания процессоров:
Процессор / Хабр
Сколько я себя помню, всегда мечтала сделать процессор. Наконец, вчера я его сделала. Не бог весть что: 8 бит, RISC, текущая рабочая частота — 4 кГц, но он работает. Пока что в программе моделирования логических цепей, но все мы знаем: «сегодня — на модели, завтра — на деле!».
Под катом несколько анимаций, краткое введение в двоичную логику для самых маленьких, короткий рассказ про основные микросхемы логики процессора и, собственно, схема.
Двоичная логика
Двоичная система счисления (для тех, кто не в курсе) — это такая система счисления, в которой нет цифр больше единицы. Такое определение многих сбивает с толку, пока они не вспомнят, что в десятичной системе счисления нет цифр больше девятки.
Двоичная система используется в компьютерах потому, что числа в ней легко кодировать напряжением: есть напряжение — значит, единица; нет напряжения — значит, ноль. Кроме того, «ноль» и «один» легко можно понимать как «ложно» и «истинно». Более того, большая часть устройств, работающих в двоичной системе счисления, обычно относится к числам как к массиву «истинностей» и «ложностей», то есть оперирует с числами как с логическими величинами. Для самых маленьких и тех, кто не в курсе, я расскажу и покажу, как работают простейшие элементы двоичной логики.
Элемент «Буфер»
Представьте, что вы сидите в своей комнате, а ваш друг — на кухне. Вы кричите ему: «Друг, скажи, в коридоре горит свет?». Друг отвечает: «Да, горит!» или «Нет, не горит». Ваш друг — буфер между источником сигнала (лампочкой в коридоре) и приемником (вами). Более того, ваш друг — не какой-нибудь там обычный буфер, а буфер управляемый. Он был бы обычным буфером, если бы постоянно кричал: «Лампочка светится» или «Лампочка не светится».
Элемент «Не» — NOT
А теперь представьте, что ваш друг — шутник, который всегда говорит неправду. И если лампочка в коридоре светится, то он скажет вам «Нет, в коридоре совсем-совсем темно», а если не светится — то «Да, в коридоре свет горит». Если у вас есть такой друг на самом деле, значит, он воплощение элемента «Не».
Элемент «Или» — OR
Для объяснения сути элемента «Или» одной лампочки и одного друга, к сожалению, не хватит. Нужно две лампочки. Итак, у вас в коридоре две лампочки — торшер, к примеру, и люстра. Вы кричите: «Друг, скажи, хотя бы одна лампочка в коридоре светит?», и ваш друг отвечает «Да» или «Нет». Очевидно, что для ответа «Нет» все лампочки обязательно должны быть выключены.
Элемент «И» — AND
Та же самая квартира, вы, друг на кухне, торшер и люстра в коридоре. На ваш вопрос «В коридоре обе лампочки горят?» вы получаете ответ «Да» или «Нет». Поздравляю, теперь ваш друг — это элемент «И».
Элемент «Исключающее Или» — XOR
Повторим еще раз эксперимент для элемента «Или», но переформулируем свой вопрос к другу: «Друг, скажи, в коридоре только одна лампочка светит?». Честный друг ответит на такой вопрос «Да» только в том случае, если в коридоре действительно горит только одна лампочка.
Сумматоры
Четвертьсумматор
Четвертьсумматором называют элемент «Исключающее Или». Почему? Давайте разберемся.
Составим таблицу сложения для двух чисел в двоичной системе счисления:
0+0= 0
0+1= 1
1+0= 1
1+1= 10
Теперь запишем таблицу истинности элемента «Исключающее Или». Для этого обозначим светящуюся лампочку за 1, потухшую — за 0, и ответы друга «Да»/«Нет» как 1 и 0 соответственно.
0 XOR 0 = 0
0 XOR 1 = 1
1 XOR 0 = 1
1 XOR 1 = 0
Очень похоже, не так ли? Таблица сложения и таблица истинности «Исключающего Или» совпадают полностью, кроме одного-единственного случая. И этот случай называется «Переполнение».
Полусумматор
При переполнении результат сложения уже не помещается в столько же разрядов, во сколько помещались слагаемые. Слагаемые — два однозначных числа (одна значащая цифра, понимаете?), а сумма — уже двузначное (две значащих цифры). Две цифры одной лампочкой («Светится»/«Не светится») уже не передать. Нужно две лампочки. Нужно — сделаем!
Кроме XOR, для сумматора нам потребуется элемент «И» (AND).
0 XOR 0 = 0 0 AND 0 = 0
0 XOR 1 = 1 0 AND 1 = 0
1 XOR 0 = 1 1 AND 0 = 0
1 XOR 1 = 0 1 AND 1 = 1
Тадам!
0+0= 00
0+1= 01
1+0= 01
1+1= 10
Наша вундервафля полусумматор работает. Его можно считать простейшим специализированным процессором, который складывает два числа. Полусумматор называется полусумматором потому, что с его помощью нельзя учитывать перенос (результат работы другого сумматора), то есть нельзя складывать три однозначных двоичных числа. В связи с этим из нескольких одноразрядных полусумматоров нельзя сделать один многоразрядный.
Я не буду вдаваться в подробности работы полных и многоразрядных сумматоров, просто надеюсь, что основную идею вы уловили.
Более сложные элементы
Мультиплексор
Предлагаю снова включить воображение. Итак, представьте. Вы живете в частном одноквартирном доме, возле двери этого дома стоит ваш почтовый ящик. Выходя на прогулку, вы замечаете странного почтальона, который стоит возле этого самого почтового ящика. И вот что он делает: достает кучу писем из сумки, читает номер на почтовом ящике, и в зависимости от номера на ящике бросает в него то или иное письмо. Почтальон работает мультиплексором. Он определенным образом (номер на конверте) определяет, какой отправить сигнал (письмо) по сигнальной линии (почтовый ящик).
Мультплексоры состоят обычно только из сочетаний элементов «И», «Или» и «Не». У одноразрядного мультиплексора один вход называется «выбор адреса», два входа с общим названием «входной сигнал» и один выход, который так и называется: «выходной сигнал».
Когда на «выбор адреса» подается 0, то «выходной сигнал» становится таким же, как первый «входной сигнал». Соответственно, когда на «выбор» подается 1, то «выходной сигнал» становится равным второму «входному сигналу».
Демультиплексор
А вот эта штучка работает с точностью до наоборот. На «выбор адреса» даем адрес, на «вход данных» даем данные, на выходе с номером «адрес» имеем данные со входа.
Счетчик
Для понимания работы счетчика вам опять понадобится ваш друг. Позовите его из кухни (надеюсь, он не сильно там скучал, и, главное, не съел всю вашу еду), и попросите делать вот что: пусть он запомнит число 0. Каждый раз, когда вы будете прикасаться к нему, он должен прибавить единицу к тому числу, которое помнит, сказать результат и запомнить его. Когда результат будет равен (допустим) 3, он должен выкрикнуть «Абракадабра!» и отвечать при следующем прикосновении, что сейчас он помнит число 0. Немного сложно? Смотрите:
Вы прикасаетесь к другу. Друг говорит «Один».
Вы прикасаетесь к другу. Друг говорит «Два».
Вы прикасаетесь к другу. Друг говорит «Три». Друг выкрикивает «Хабрахабр!». Критическая атака! Вы временно парализованы и не можете двигаться.
Вы прикасаетесь к другу. Друг говорит «Ноль».
Ну, и так далее. Очень просто, верно?
Вы, конечно, поняли, что ваш друг сейчас — это счетчик. Прикосновение к другу можно считать «тактирующим сигналом» или, попросту говоря, сигналом продолжения счета. Крик «Абракадабра» показывает, что запомненное значение в счетчике — максимальное, и что при следующем тактирующем сигнале счетчик будет установлен в ноль. Есть два отличия двоичного счетчика от вашего друга. Первое: настоящий двоичный счетчик выдает запомненное значение в двоичном виде. Второе: он всегда делает только то, что вы ему говорите, и никогда не опускается до дурацких шуточек, способных нарушить работу всей процессорной системы.
Память
Триггер
Давайте продолжим издеваться над вашим несчастным (возможно, даже воображаемым) другом. Пусть теперь он запомнит число ноль. Когда вы касаетесь его левой руки, он должен запоминать число ноль, а когда правой — число один. При вопросе «Какое число ты помнишь?» друг должен всегда отвечать то число, которое запоминал — ноль или один.
Простейшей запоминающей ячейкой является RS-триггер («триггер» значит «переключатель»). RS-триггер может хранить в себе один бит данных («ноль»/«один»), и имеет два входа. Вход Set/Установка (совсем как левая рука вашего друга) записывает в триггер «один», а вход Reset/Сброс (соответственно, правая рука) — «ноль».
Регистр
Немного сложнее устроен регистр. Ваш друг превращается в регистр тогда, когда вы просите его что-нибудь запомнить, а потом говорите «Эй, напомни мне, что я говорил тебе запомнить?», и друг правильно отвечает.
Регистр обычно может хранить в себе чуть больше, чем один бит. У него обязательно есть вход данных, выход данных и вход разрешения записи. С выхода данных вы в любой момент можете прочитать то, что в этом регистре записано. На вход данных вы можете подавать те данные, которые хотите в этот регистр записать. Можете подавать данные до тех пор, пока не надоест. В регистр все равно ничего не запишется до тех пор, пока на вход разрешения записи не подать один, то есть «логическую единицу».
Сдвиговый регистр
Вы когда-нибудь стояли в очередях? Наверняка стояли. Значит, вы представляете, каково быть данными в сдвиговом регистре. Люди приходят и становятся в конец очереди. Первый человек в очереди заходит в кабинет к большой шишке. Тот, кто был вторым в очереди, становится первым, а тот, кто был третьим — теперь второй, и так далее. Очередь — это такой хитрый сдвиговый регистр, из которого «данные» (ну, то есть люди) могут убегать по делам, предварительно предупредив соседей по очереди. В настоящем сдвиговом регистре, разумеется, «данные» из очереди сбегать не могут.
Итак, у сдвигового регистра есть вход данных (через него данные попадают в «очередь») и выход данных (из которого можно прочитать самую первую запись в «очереди»). Еще у сдвигового регистра есть вход «сдвинуть регистр». Как только на этот вход приходит «логическая единица», вся очередь сдвигается.
Есть одно важное различие между очередью и сдвиговым регистром. Если сдвиговый регистр расчитан на четыре записи (например, на четыре байта), то первая в очереди запись дойдет до выхода из регистра только после четырех сигналов на вход «сдвинуть регистр».
Оперативная память
Если много-много триггеров объединить в регистры, а много-много регистров объединить в одной микросхеме, то получится микросхема оперативной памяти. У микросхемы памяти обычно есть вход адреса, двунаправленный вход данных (то есть в этот вход можно записывать, и с него же можно считывать) и вход разрешения записи. На вход адреса подаем какое-нибудь число, и это число выберет определенную ячейку памяти. После этого на входе/выходе данных мы можем прочитать то, что записано в эту самую ячейку.
Теперь мы одновременно подадим на вход/выход данных то, что хотим в эту ячейку записать, а на вход разрешения записи — «логическую единицу». Результат немного предсказуем, не так ли?
Процессор
BitBitJump
Процессоры иногда делят на CISC — те, которые умеют выполнять много разных команд, и RISC — те, которые умеют выполнять мало команд, но выполняют их хорошо. Одним прекрасным вечером мне подумалось: а было бы здорово, если бы можно было сделать полноценный процессор, который умеет выполнять всего одну команду. Вскоре я узнала, что существует целый класс однокомандных процессоров — OISC, чаще всего они используют команду Subleq (вычесть, и если меньше или равно нулю, то перейти) или Subeq (вычесть, и если равно нулю, то перейти). Изучая различные варианты OISC-процессоров, я нашла в сети сайт Олега Мазонки, который разработал простейший однокомандный язык BitBitJump. Единственная команда этого языка так и называется — BitBitJump (скопировать бит и перейти по адресу). Этот, безусловно эзотерический, язык является полным по Тьюрингу — то есть на нем можно реализовать любой компьютерный алгоритм.
Подробное описание BitBitJump и ассемблер для этого языка можно найти на сайте разработчика. Для описания алгоритма работы процессора достаточно знать следующее:
1. При включении процессора в регистрах PC, A и B записаны 0
2. Считываем ячейку памяти с адресом PC и сохраняем прочитанное в регистр A
3. Увеличиваем PC
4. Считываем ячейку памяти с адресом PC и сохраняем прочитанное в регистр B
5. Увеличиваем PC
6. Записываем в ячейку с адресом, записанным в регистре B, содержимое бита с адресом А.
7. Считываем ячейку памяти с адресом PC и сохраняем прочитанное в регистр B
8. Записываем в регистр PC содержимое регистра B
9. Переходим к пункту 2 нашего плана10. PROFIT!!!
К сожалению, алгоритм бесконечный, и потому PROFIT достигнут не будет.
Собственно, схема
Схема строилась стихийно, поэтому правят бал в ней страх, ужас и кавардак. Тем не менее, она работает, и работает прилично. Чтобы включить процессор, нужно:
1. Ввести программу в ОЗУ
2. Нажать на включатель
3. Установить счетчик в положение 4 (это можно делать и аппаратно, но схема стала бы еще более громоздкой)
4. Включить тактовый генератор
Как видите, использованы один регистр, один сдвиговый регистр, одна микросхема ОЗУ, два двоичных счетчика, один демультиплексор (представленный компараторами), два мультиплексора и немного чистой логики.
Можете скачать схему в формате circ для программы Logisim, и поиграться.
Что дальше?
Во-первых, можно увеличить разрядность процессора — заменив 8-битные элементы на 16-битные.
Во-вторых, можно вынести ОЗУ из процессора, и добавить несложную схему, которая будет приостанавливать процессор, изменять ОЗУ и снова включать процессор. Такая схема будет выполнять функции простого контроллера ввода-вывода. Тогда можно будет сделать на базе этого процессора калькулятор, контроллер или еще какую-нибудь забавную бесполезную штуку.
В-третьих, можно воплотить всю эту схему в железе. Что я собираюсь сделать. Как только сделаю — обязательно расскажу и покажу.
Спасибо всем за внимание!
P.S. Ссылки (для тех, кому лень читать):
1. Процессоры URISC — ru.wikipedia.org/wiki/Urisc
2. Сайт языка BitBitJump — mazonka.com/bbj/index.html
3. Программа для моделирования логических схем Logisim — http://ozark.hendrix.edu/~burch/logisim/
4. Самодельный URISC (ORISC) процессор для Logisim — narod.ru/disk/31367690001/oo.circ.html
От песка до процессора / Блог компании Intel / Хабр
Сложно в это поверить, но современный процессор является самым сложным готовым продуктом на Земле – а ведь, казалось бы, чего сложного в этом куске железа?
Как и обещал – подробный рассказ о том, как делают процессоры… начиная с песка. Все, что вы хотели знать, но боялись спросить )
Я уже рассказывал о том, «Где производят процессоры» и о том, какие «Трудности производства» на этом пути стоят. Сегодня речь пойдет непосредственно про само производство – «от и до».
Производство процессоров
Когда фабрика для производства процессоров по новой технологии построена, у нее есть 4 года на то, чтобы окупить вложенные средства (более $5млрд) и принести прибыль. Из несложных секретных расчетов получается, что фабрика должна производить не менее 100 работающих пластин в час.
Вкратце процесс изготовления процессора выглядит так: из расплавленного кремния на специальном оборудовании выращивают монокристалл цилиндрической формы. Получившийся слиток охлаждают и режут на «блины», поверхность которых тщательно выравнивают и полируют до зеркального блеска. Затем в «чистых комнатах» полупроводниковых заводов на кремниевых пластинах методами фотолитографии и травления создаются интегральные схемы. После повторной очистки пластин, специалисты лаборатории под микроскопом производят выборочное тестирование процессоров – если все «ОК», то готовые пластины разрезают на отдельные процессоры, которые позже заключают в корпуса.
Уроки химии
Давайте рассмотрим весь процесс более подробно. Содержание кремния в земной коре составляет порядка 25-30% по массе, благодаря чему по распространённости этот элемент занимает второе место после кислорода. Песок, особенно кварцевый, имеет высокий процент содержания кремния в виде диоксида кремния (SiO2) и в начале производственного процесса является базовым компонентом для создания полупроводников.
Первоначально берется SiO2 в виде песка, который в дуговых печах (при температуре около 1800°C) восстанавливают коксом:
SiO2 + 2C = Si + 2CO
Такой кремний носит название «технический» и имеет чистоту 98-99.9%. Для производства процессоров требуется гораздо более чистое сырье, называемое «электронным кремнием» — в таком должно быть не более одного чужеродного атома на миллиард атомов кремния. Для очистки до такого уровня, кремний буквально «рождается заново». Путем хлорирования технического кремния получают тетрахлорид кремния (SiCl4), который в дальнейшем преобразуется в трихлорсилан (SiHCl3):
3SiCl4 + 2H2 + Si 4SiHCl3
Данные реакции с использованием рецикла образующихся побочных кремнийсодержащих веществ снижают себестоимость и устраняют экологические проблемы:
2SiHCl3 SiH2Cl2 + SiCl4
2SiH2Cl2 SiH3Cl + SiHCl3
2SiH3Cl SiH4 + SiH2Cl2
SiH4 Si + 2H2
Получившийся в результате водород можно много где использовать, но самое главное то, что был получен «электронный» кремний, чистый-пречистый (99,9999999%). Чуть позже в расплав такого кремния опускается затравка («точка роста»), которая постепенно вытягивается из тигля. В результате образуется так называемая «буля» — монокристалл высотой со взрослого человека. Вес соответствующий — на производстве такая дуля весит порядка 100 кг.
Слиток шкурят «нулёвкой» 🙂 и режут алмазной пилой. На выходе – пластины (кодовое название «вафля») толщиной около 1 мм и диаметром 300 мм (~12 дюймов; именно такие используются для техпроцесса в 32нм с технологией HKMG, High-K/Metal Gate). Когда-то давно Intel использовала диски диаметром 50мм (2″), а в ближайшем будущем уже планируется переход на пластины с диаметром в 450мм – это оправдано как минимум с точки зрения снижения затрат на производство чипов. К слову об экономии — все эти кристаллы выращиваются вне Intel; для процессорного производства они закупаются в другом месте.
Каждую пластину полируют, делают идеально ровной, доводя ее поверхность до зеркального блеска.
Производство чипов состоит более чем из трёх сотен операций, в результате которых более 20 слоёв образуют сложную трёхмерную структуру – доступный на Хабре объем статьи не позволит рассказать вкратце даже о половине из этого списка 🙂 Поэтому совсем коротко и лишь о самых важных этапах.
Итак. В отшлифованные кремниевые пластины необходимо перенести структуру будущего процессора, то есть внедрить в определенные участки кремниевой пластины примеси, которые в итоге и образуют транзисторы. Как это сделать? Вообще, нанесение различных слоев на процессорную подложу это целая наука, ведь даже в теории такой процесс непрост (не говоря уже о практике, с учетом масштабов)… но ведь так приятно разобраться в сложном 😉 Ну или хотя бы попытаться разобраться.
Фотолитография
Проблема решается с помощью технологии фотолитографии — процесса избирательного травления поверхностного слоя с использованием защитного фотошаблона. Технология построена по принципу «свет-шаблон-фоторезист» и проходит следующим образом:
— На кремниевую подложку наносят слой материала, из которого нужно сформировать рисунок. На него наносится фоторезист — слой полимерного светочувствительного материала, меняющего свои физико-химические свойства при облучении светом.
— Производится экспонирование (освещение фотослоя в течение точно установленного промежутка времени) через фотошаблон
— Удаление отработанного фоторезиста.
Нужная структура рисуется на фотошаблоне — как правило, это пластинка из оптического стекла, на которую фотографическим способом нанесены непрозрачные области. Каждый такой шаблон содержит один из слоев будущего процессора, поэтому он должен быть очень точным и практичным.
Иной раз осаждать те или иные материалы в нужных местах пластины просто невозможно, поэтому гораздо проще нанести материал сразу на всю поверхность, убрав лишнее из тех мест, где он не нужен — на изображении выше синим цветом показано нанесение фоторезиста.
Пластина облучается потоком ионов (положительно или отрицательно заряженных атомов), которые в заданных местах проникают под поверхность пластины и изменяют проводящие свойства кремния (зеленые участки — это внедренные чужеродные атомы).
Как изолировать области, не требующие последующей обработки? Перед литографией на поверхность кремниевой пластины (при высокой температуре в специальной камере) наносится защитная пленка диэлектрика – как я уже рассказывал, вместо традиционного диоксида кремния компания Intel стала использовать High-K-диэлектрик. Он толще диоксида кремния, но в то же время у него те же емкостные свойства. Более того, в связи с увеличением толщины уменьшен ток утечки через диэлектрик, а как следствие – стало возможным получать более энергоэффективные процессоры. В общем, тут гораздо сложнее обеспечить равномерность этой пленки по всей поверхности пластины — в связи с этим на производстве применяется высокоточный температурный контроль.
Так вот. В тех местах, которые будут обрабатываться примесями, защитная пленка не нужна – её аккуратно снимают при помощи травления (удаления областей слоя для формирования многослойной структуры с определенными свойствами). А как снять ее не везде, а только в нужных областях? Для этого поверх пленки необходимо нанести еще один слой фоторезиста – за счет центробежной силы вращающейся пластины, он наносится очень тонким слоем.
В фотографии свет проходил через негативную пленку, падал на поверхность фотобумаги и менял ее химические свойства. В фотолитографии принцип схожий: свет пропускается через фотошаблон на фоторезист, и в тех местах, где он прошел через маску, отдельные участки фоторезиста меняют свойства. Через маски пропускается световое излучение, которое фокусируется на подложке. Для точной фокусировки необходима специальная система линз или зеркал, способная не просто уменьшить, изображение, вырезанное на маске, до размеров чипа, но и точно спроецировать его на заготовке. Напечатанные пластины, как правило, в четыре раза меньше, чем сами маски.
Весь отработанный фоторезист (изменивший свою растворимость под действием облучения) удаляется специальным химическим раствором – вместе с ним растворяется и часть подложки под засвеченным фоторезистом. Часть подложки, которая была закрыта от света маской, не растворится. Она образует проводник или будущий активный элемент – результатом такого подхода становятся различные картины замыканий на каждом слое микропроцессора.
Собственно говоря, все предыдущие шаги были нужны для того, чтобы создать в необходимых местах полупроводниковые структуры путем внедрения донорной (n-типа) или акцепторной (p-типа) примеси. Допустим, нам нужно сделать в кремнии область концентрации носителей p-типа, то есть зону дырочной проводимости. Для этого пластину обрабатывают с помощью устройства, которое называется имплантер — ионы бора с огромной энергией выстреливаются из высоковольтного ускорителя и равномерно распределяются в незащищенных зонах, образованных при фотолитографии.
Там, где диэлектрик был убран, ионы проникают в слой незащищенного кремния – в противном случае они «застревают» в диэлектрике. После очередного процесса травления убираются остатки диэлектрика, а на пластине остаются зоны, в которых локально есть бор. Понятно, что у современных процессоров может быть несколько таких слоев — в таком случае на получившемся рисунке снова выращивается слой диэлектрика и далее все идет по протоптанной дорожке — еще один слой фоторезиста, процесс фотолитографии (уже по новой маске), травление, имплантация… ну вы поняли.
Характерный размер транзистора сейчас — 32 нм, а длина волны, которой обрабатывается кремний — это даже не обычный свет, а специальный ультрафиолетовый эксимерный лазер — 193 нм. Однако законы оптики не позволяют разрешить два объекта, находящиеся на расстоянии меньше, чем половина длины волны. Происходит это из-за дифракции света. Как быть? Применять различные ухищрения — например, кроме упомянутых эксимерных лазеров, светящих далеко в ультрафиолетовом спектре, в современной фотолитографии используется многослойная отражающая оптика с использованием специальных масок и специальный процесс иммерсионной (погружной) фотолитографии.
Логические элементы, которые образовались в процессе фотолитографии, должны быть соединены друг с другом. Для этого пластины помещают в раствор сульфата меди, в котором под действием электрического тока атомы металла «оседают» в оставшихся «проходах» — в результате этого гальванического процесса образуются проводящие области, создающие соединения между отдельными частями процессорной «логики». Излишки проводящего покрытия убираются полировкой.
Финишная прямая
Ура – самое сложное позади. Осталось хитрым способом соединить «остатки» транзисторов — принцип и последовательность всех этих соединений (шин) и называется процессорной архитектурой. Для каждого процессора эти соединения различны – хоть схемы и кажутся абсолютно плоскими, в некоторых случаях может использоваться до 30 уровней таких «проводов». Отдаленно (при очень большом увеличении) все это похоже на футуристическую дорожную развязку – и ведь кто-то же эти клубки проектирует!
Когда обработка пластин завершена, пластины передаются из производства в монтажно-испытательный цех. Там кристаллы проходят первые испытания, и те, которые проходят тест (а это подавляющее большинство), вырезаются из подложки специальным устройством.
На следующем этапе процессор упаковывается в подложку (на рисунке – процессор Intel Core i5, состоящий из CPU и чипа HD-графики).
Привет, сокет!
Подложка, кристалл и теплораспределительная крышка соединяются вместе – именно этот продукт мы будем иметь ввиду, говоря слово «процессор». Зеленая подложка создает электрический и механический интерфейс (для электрического соединения кремниевой микросхемы с корпусом используется золото), благодаря которому станет возможным установка процессора в сокет материнской платы – по сути, это просто площадка, на которой разведены контакты от маленького чипа. Теплораспределительная крышка является термоинтерфейсом, охлаждающим процессор во время работы – именно к этой крышке будут примыкать система охлаждения, будь то радиатор кулера или здоровый водоблок.
Сокет (разъём центрального процессора) — гнездовой или щелевой разъём, предназначенный для установки центрального процессора. Использование разъёма вместо прямого распаивания процессора на материнской плате упрощает замену процессора для модернизации или ремонта компьютера. Разъём может быть предназначен для установки собственно процессора или CPU-карты (например, в Pegasos). Каждый разъём допускает установку только определённого типа процессора или CPU-карты.
На завершающем этапе производства готовые процессоры проходят финальные испытания на предмет соответствия основным характеристикам – если все в порядке, то процессоры сортируются в нужном порядке в специальные лотки – в таком виде процессоры уйдут производителям или поступят в OEM-продажу. Еще какая-то партия пойдет на продажу в виде BOX-версий – в красивой коробке вместе со стоковой системой охлаждения.
The end
Теперь представьте себе, что компания анонсирует, например, 20 новых процессоров. Все они различны между собой – количество ядер, объемы кэша, поддерживаемые технологии… В каждой модели процессора используется определенное количество транзисторов (исчисляемое миллионами и даже миллиардами), свой принцип соединения элементов… И все это надо спроектировать и создать/автоматизировать – шаблоны, линзы, литографии, сотни параметров для каждого процесса, тестирование… И все это должно работать круглосуточно, сразу на нескольких фабриках… В результате чего должны появляться устройства, не имеющие права на ошибку в работе… А стоимость этих технологических шедевров должна быть в рамках приличия… Почти уверен в том, что вы, как и я, тоже не можете представить себе всего объема проделываемой работы, о которой я и постарался сегодня рассказать.
Ну и еще кое-что более удивительное. Представьте, что вы без пяти минут великий ученый — аккуратно сняли теплораспределительную крышку процессора и в огромный микроскоп смогли увидеть структуру процессора – все эти соединения, транзисторы… даже что-то на бумажке зарисовали, чтобы не забыть. Как думаете, легко ли изучить принципы работы процессора, располагая только этими данными и данными о том, какие задачи с помощью этого процессора можно решать? Мне кажется, примерно такая картина сейчас видна ученым, которые пытаются на подобном уровне изучить работу человеческого мозга. Только если верить стэнфордским микробиологам, в одном человеческом мозге находится больше «транзисторов», чем во всей мировой IT-инфраструктуре. Интересно, правда?
BONUS
Хватило сил дочитать до этого абзаца? ) Поздравляю – приятно, что я постарался не зря. Тогда предлагаю откинуться на спинку кресла и посмотреть всё описанное выше, но в виде более наглядного видеоролика – без него статья была бы не полной.
Эту статью я писал сам, пытаясь вникнуть в тонкости процесса процессоростроения. Я к тому, что в статье могут быть какие-то неточности или ошибки — если найдете что-то, дайте знать. А вообще, чтобы окончательно закрепить весь прочитанный материал и наглядно понять то, что было недопонято в моей статье, пройдите по этой ссылке. Теперь точно всё.
Успехов!
Процессоры, ядра и потоки. Топология систем / Блог компании Intel / Хабр
В этой статье я попытаюсь описать терминологию, используемую для описания систем, способных исполнять несколько программ параллельно, то есть многоядерных, многопроцессорных, многопоточных. Разные виды параллелизма в ЦПУ IA-32 появлялись в разное время и в несколько непоследовательном порядке. Во всём этом довольно легко запутаться, особенно учитывая, что операционные системы заботливо прячут детали от не слишком искушённых прикладных программ.
Используемая далее терминология используется в документации процессорам Intel. Другие архитектуры могут иметь другие названия для похожих понятий. Там, где они мне известны, я буду их упоминать.
Цель статьи — показать, что при всём многообразии возможных конфигураций многопроцессорных, многоядерных и многопоточных систем для программ, исполняющихся на них, создаются возможности как для абстракции (игнорирования различий), так и для учёта специфики (возможность программно узнать конфигурацию).
Предупреждение о знаках ®, ™, © в статье Мой комментарий объясняет, почему сотрудники компаний должны в публичных коммуникациях использовать знаки авторского права. В этой статье их пришлось использовать довольно часто.
Процессор
Конечно же, самый древний, чаще всего используемый и неоднозначный термин — это «процессор».
В современном мире процессор — это то (package), что мы покупаем в красивой Retail коробке или не очень красивом OEM-пакетике. Неделимая сущность, вставляемая в разъём (socket) на материнской плате. Даже если никакого разъёма нет и снять его нельзя, то есть если он намертво припаян, это один чип.
Мобильные системы (телефоны, планшеты, ноутбуки) и большинство десктопов имеют один процессор. Рабочие станции и сервера иногда могут похвастаться двумя или больше процессорами на одной материнской плате.
Поддержка нескольких центральных процессоров в одной системе требует многочисленных изменений в её дизайне. Как минимум, необходимо обеспечить их физическое подключение (предусмотреть несколько сокетов на материнской плате), решить вопросы идентификации процессоров (см. далее в этой статье, а также мою предыдущую заметку), согласования доступов к памяти и доставки прерываний (контроллер прерываний должен уметь маршрутизировать прерывания на несколько процессоров) и, конечно же, поддержки со стороны операционной системы. Я, к сожалению, не смог найти документального упоминания момента создания первой многопроцессорной системы на процессорах Intel, однако Википедия утверждает, что Sequent Computer Systems поставляла их уже в 1987 году, используя процессоры Intel 80386. Широко распространённой поддержка же нескольких чипов в одной системе становится доступной, начиная с Intel® Pentium.
Если процессоров несколько, то каждый из них имеет собственный разъём на плате. У каждого из них при этом имеются полные независимые копии всех ресурсов, таких как регистры, исполняющие устройства, кэши. Делят они общую память — RAM. Память может подключаться к ним различными и довольно нетривиальными способами, но это отдельная история, выходящая за рамки этой статьи. Важно то, что при любом раскладе для исполняемых программ должна создаваться иллюзия однородной общей памяти, доступной со всех входящих в систему процессоров.
К взлёту готов! Intel® Desktop Board D5400XS
Ядро
Исторически многоядерность в Intel IA-32 появилась позже Intel® HyperThreading, однако в логической иерархии она идёт следующей.
Казалось бы, если в системе больше процессоров, то выше её производительность (на задачах, способных задействовать все ресурсы). Однако, если стоимость коммуникаций между ними слишком велика, то весь выигрыш от параллелизма убивается длительными задержками на передачу общих данных. Именно это наблюдается в многопроцессорных системах — как физически, так и логически они находятся очень далеко друг от друга. Для эффективной коммуникации в таких условиях приходится придумывать специализированные шины, такие как Intel® QuickPath Interconnect. Энергопотребление, размеры и цена конечного решения, конечно, от всего этого не понижаются. На помощь должна прийти высокая интеграция компонент — схемы, исполняющие части параллельной программы, надо подтащить поближе друг к другу, желательно на один кристалл. Другими словами, в одном процессоре следует организовать несколько ядер, во всём идентичных друг другу, но работающих независимо.
Первые многоядерные процессоры IA-32 от Intel были представлены в 2005 году. С тех пор среднее число ядер в серверных, десктопных, а ныне и мобильных платформах неуклонно растёт.
В отличие от двух одноядерных процессоров в одной системе, разделяющих только память, два ядра могут иметь также общие кэши и другие ресурсы, отвечающие за взаимодействие с памятью. Чаще всего кэши первого уровня остаются приватными (у каждого ядра свой), тогда как второй и третий уровень может быть как общим, так и раздельным. Такая организация системы позволяет сократить задержки доставки данных между соседними ядрами, особенно если они работают над общей задачей.
Микроснимок четырёхядерного процессора Intel с кодовым именем Nehalem. Выделены отдельные ядра, общий кэш третьего уровня, а также линки QPI к другим процессорам и общий контроллер памяти.
Гиперпоток
До примерно 2002 года единственный способ получить систему IA-32, способную параллельно исполнять две или более программы, состоял в использовании именно многопроцессорных систем. В Intel® Pentium® 4, а также линейке Xeon с кодовым именем Foster (Netburst) была представлена новая технология — гипертреды или гиперпотоки, — Intel® HyperThreading (далее HT).
Ничто не ново под луной. HT — это частный случай того, что в литературе именуется одновременной многопоточностью (simultaneous multithreading, SMT). В отличие от «настоящих» ядер, являющихся полными и независимыми копиями, в случае HT в одном процессоре дублируется лишь часть внутренних узлов, в первую очередь отвечающих за хранение архитектурного состояния — регистры. Исполнительные же узлы, ответственные за организацию и обработку данных, остаются в единственном числе, и в любой момент времени используются максимум одним из потоков. Как и ядра, гиперпотоки делят между собой кэши, однако начиная с какого уровня — это зависит от конкретной системы.
Я не буду пытаться объяснить все плюсы и минусы дизайнов с SMT вообще и с HT в частности. Интересующийся читатель может найти довольно подробное обсуждение технологии во многих источниках, и, конечно же, в Википедии. Однако отмечу следующий важный момент, объясняющий текущие ограничения на число гиперпотоков в реальной продукции.
Ограничения потоков
В каких случаях наличие «нечестной» многоядерности в виде HT оправдано? Если один поток приложения не в состоянии загрузить все исполняющие узлы внутри ядра, то их можно «одолжить» другому потоку. Это типично для приложений, имеющих «узкое место» не в вычислениях, а при доступе к данным, то есть часто генерирующих промахи кэша и вынужденных ожидать доставку данных из памяти. В это время ядро без HT будет вынуждено простаивать. Наличие же HT позволяет быстро переключить свободные исполняющие узлы к другому архитектурному состоянию (т.к. оно как раз дублируется) и исполнять его инструкции. Это — частный случай приёма под названием latency hiding, когда одна длительная операция, в течение которой полезные ресурсы простаивают, маскируется параллельным выполнением других задач. Если приложение уже имеет высокую степень утилизации ресурсов ядра, наличие гиперпотоков не позволит получить ускорение — здесь нужны «честные» ядра.
Типичные сценарии работы десктопных и серверных приложений, рассчитанных на машинные архитектуры общего назначения, имеют потенциал к параллелизму, реализуемому с помощью HT. Однако этот потенциал быстро «расходуется». Возможно, по этой причине почти на всех процессорах IA-32 число аппаратных гиперпотоков не превышает двух. На типичных сценариях выигрыш от использования трёх и более гиперпотоков был бы невелик, а вот проигрыш в размере кристалла, его энергопотреблении и стоимости значителен.
Другая ситуация наблюдается на типичных задачах, выполняемых на видеоускорителях. Поэтому для этих архитектур характерно использование техники SMT с бóльшим числом потоков. Так как сопроцессоры Intel® Xeon Phi (представленные в 2010 году) идеологически и генеалогически довольно близки к видеокартам, на них может быть четыре гиперпотока на каждом ядре — уникальная для IA-32 конфигурация.
Логический процессор
Из трёх описанных «уровней» параллелизма (процессоры, ядра, гиперпотоки) в конкретной системе могут отсутствовать некоторые или даже все. На это влияют настройки BIOS (многоядерность и многопоточность отключаются независимо), особенности микроархитектуры (например, HT отсутствовал в Intel® Core™ Duo, но был возвращён с выпуском Nehalem) и события при работе системы (многопроцессорные сервера могут выключать отказавшие процессоры в случае обнаружения неисправностей и продолжать «лететь» на оставшихся). Каким образом этот многоуровневый зоопарк параллелизма виден операционной системе и, в конечном счёте, прикладным приложениям?
Далее для удобства обозначим количества процессоров, ядер и потоков в некоторой системе тройкой (x, y, z), где x — это число процессоров, y — число ядер в каждом процессоре, а z — число гиперпотоков в каждом ядре. Далее я буду называть эту тройку топологией — устоявшийся термин, мало что имеющий с разделом математики. Произведение p = xyz определяет число сущностей, именуемых логическими процессорами системы. Оно определяет полное число независимых контекстов прикладных процессов в системе с общей памятью, исполняющихся параллельно, которые операционная система вынуждена учитывать. Я говорю «вынуждена», потому что она не может управлять порядком исполнения двух процессов, находящихся на различных логических процессорах. Это относится в том числе к гиперпотокам: хотя они и работают «последовательно» на одном ядре, конкретный порядок диктуется аппаратурой и недоступен для наблюдения или управления программам.
Чаще всего операционная система прячет от конечных приложений особенности физической топологии системы, на которой она запущена. Например, три следующие топологии: (2, 1, 1), (1, 2, 1) и (1, 1, 2) — ОС будет представлять в виде двух логических процессоров, хотя первая из них имеет два процессора, вторая — два ядра, а третья — всего лишь два потока.
Windows Task Manager показывает 8 логических процессоров; но сколько это в процессорах, ядрах и гиперпотоках?
Linux top
показывает 4 логических процессора.
Это довольно удобно для создателей прикладных приложений — им не приходится иметь дело с зачастую несущественными для них особенностями аппаратуры.
Программное определение топологии
Конечно, абстрагирование топологии в единственное число логических процессоров в ряде случаев создаёт достаточно оснований для путаницы и недоразумений (в жарких Интернет-спорах). Вычислительные приложения, желающие выжать из железа максимум производительности, требуют детального контроля над тем, где будут размещены их потоки: поближе друг к другу на соседних гиперпотоках или же наоборот, подальше на разных процессорах. Скорость коммуникаций между логическими процессорами в составе одного ядра или процессора значительно выше, чем скорость передачи данных между процессорами. Возможность неоднородности в организации оперативной памяти также усложняет картину.
Информация о топологии системы в целом, а также положении каждого логического процессора в IA-32 доступна с помощью инструкции CPUID. С момента появления первых многопроцессорных систем схема идентификации логических процессоров несколько раз расширялась. К настоящему моменту её части содержатся в листах 1, 4 и 11 CPUID. Какой из листов следует смотреть, можно определить из следующей блок-схемы, взятой из статьи [2]:
Я не буду здесь утомлять всеми подробностями отдельных частей этого алгоритма. Если возникнет интерес, то этому можно посвятить следующую часть этой статьи. Отошлю интересующегося читателя к [2], в которой этот вопрос разбирается максимально подробно. Здесь же я сначала кратко опишу, что такое APIC и как он связан с топологией. Затем рассмотрим работу с листом 0xB (одиннадцать в десятичном счислении), который на настоящий момент является последним словом в «апикостроении».
APIC ID
Local APIC (advanced programmable interrupt controller) — это устройство (ныне входящее в состав процессора), отвечающее за работу с прерываниями, приходящими к конкретному логическому процессору. Свой собственный APIC есть у каждого логического процессора. И каждый из них в системе должен иметь уникальное значение APIC ID. Это число используется контроллерами прерываний для адресации при доставке сообщений, а всеми остальными (например, операционной системой) — для идентификации логических процессоров. Спецификация на этот контроллер прерываний эволюционировала, пройдя от микросхемы Intel 8259 PIC через Dual PIC, APIC и xAPIC к x2APIC.
В настоящий момент ширина числа, хранящегося в APIC ID, достигла полных 32 бит, хотя в прошлом оно было ограничено 16, а ещё раньше — только 8 битами. Нынче остатки старых дней раскиданы по всему CPUID, однако в CPUID.0xB.EDX[31:0] возвращаются все 32 бита APIC ID. На каждом логическом процессоре, независимо исполняющем инструкцию CPUID, возвращаться будет своё значение.
Выяснение родственных связей
Значение APIC ID само по себе ничего не говорит о топологии. Чтобы узнать, какие два логических процессора находятся внутри одного физического (т.е. являются «братьями» гипертредами), какие два — внутри одного процессора, а какие оказались и вовсе в разных процессорах, надо сравнить их значения APIC ID. В зависимости от степени родства некоторые их биты будут совпадать. Эта информация содержится в подлистьях CPUID.0xB, которые кодируются с помощью операнда в ECX. Каждый из них описывает положение битового поля одного из уровней топологии в EAX[5:0] (точнее, число бит, которые нужно сдвинуть в APIC ID вправо, чтобы убрать нижние уровни топологии), а также тип этого уровня — гиперпоток, ядро или процессор, — в ECX[15:8].
У логических процессоров, находящихся внутри одного ядра, будут совпадать все биты APIC ID, кроме принадлежащих полю SMT. Для логических процессоров, находящихся в одном процессоре, — все биты, кроме полей Core и SMT. Поскольку число подлистов у CPUID.0xB может расти, данная схема позволит поддержать описание топологий и с бóльшим числом уровней, если в будущем возникнет необходимость. Более того, можно будет ввести промежуточные уровни между уже существующими.
Важное следствие из организации данной схемы заключается в том, что в наборе всех APIC ID всех логических процессоров системы могут быть «дыры», т.е. они не будут идти последовательно. Например, во многоядерном процессоре с выключенным HT все APIC ID могут оказаться чётными, так как младший бит, отвечающий за кодирование номера гиперпотока, будет всегда нулевым.
Отмечу, что CPUID.0xB — не единственный источник информации о логических процессорах, доступный операционной системе. Список всех процессоров, доступный ей, вместе с их значениями APIC ID, кодируется в таблице MADT ACPI [3, 4].
Операционные системы и топология
Операционные системы предоставляют информацию о топологии логических процессоров приложениям с помощью своих собственных интерфейсов.
В Linux информация о топологии содержится в псевдофайле /proc/cpuinfo
, а также выводе команды dmidecode
. В примере ниже я фильтрую содержимое cpuinfo на некоторой четырёхядерной системе без HT, оставляя только записи, относящиеся к топологии:
Скрытый текст
ggg@shadowbox:~$ cat /proc/cpuinfo |grep 'processor\|physical\ id\|siblings\|core\|cores\|apicid'
processor : 0
physical id : 0
siblings : 4
core id : 0
cpu cores : 2
apicid : 0
initial apicid : 0
processor : 1
physical id : 0
siblings : 4
core id : 0
cpu cores : 2
apicid : 1
initial apicid : 1
processor : 2
physical id : 0
siblings : 4
core id : 1
cpu cores : 2
apicid : 2
initial apicid : 2
processor : 3
physical id : 0
siblings : 4
core id : 1
cpu cores : 2
apicid : 3
initial apicid : 3
В FreeBSD топология сообщается через механизм sysctl в переменной kern.sched.topology_spec в виде XML:
Скрытый текст
user@host:~$ sysctl kern.sched.topology_spec
kern.sched.topology_spec: <groups>
<group level="1" cache-level="0">
<cpu count="8" mask="0xff">0, 1, 2, 3, 4, 5, 6, 7</cpu>
<children>
<group level="2" cache-level="2">
<cpu count="8" mask="0xff">0, 1, 2, 3, 4, 5, 6, 7</cpu>
<children>
<group level="3" cache-level="1">
<cpu count="2" mask="0x3">0, 1</cpu>
<flags><flag name="THREAD">THREAD group</flag><flag name="SMT">SMT group</flag></flags>
</group>
<group level="3" cache-level="1">
<cpu count="2" mask="0xc">2, 3</cpu>
<flags><flag name="THREAD">THREAD group</flag><flag name="SMT">SMT group</flag></flags>
</group>
<group level="3" cache-level="1">
<cpu count="2" mask="0x30">4, 5</cpu>
<flags><flag name="THREAD">THREAD group</flag><flag name="SMT">SMT group</flag></flags>
</group>
<group level="3" cache-level="1">
<cpu count="2" mask="0xc0">6, 7</cpu>
<flags><flag name="THREAD">THREAD group</flag><flag name="SMT">SMT group</flag></flags>
</group>
</children>
</group>
</children>
</group>
</groups>
В MS Windows 8 сведения о топологии можно увидеть в диспетчере задач Task Manager.
Скрытый текст
Также их предоставляет консольная утилита Sysinternals Coreinfo и API вызов GetLogicalProcessorInformation.
Полная картина
Проиллюстрирую ещё раз отношения между понятиями «процессор», «ядро», «гиперпоток» и «логический процессор» на нескольких примерах.
Система (2, 2, 2)
Система (2, 4, 1)
Система (4, 1, 1)
Прочие вопросы
В этот раздел я вынес некоторые курьёзы, возникающие из-за многоуровневой организации логических процессоров.
Кэши
Как я уже упоминал, кэши в процессоре тоже образуют иерархию, и она довольно сильно связано с топологией ядер, однако не определяется ей однозначно. Для определения того, какие кэши для каких логических процессоров общие, а какие нет, используется вывод CPUID.4 и её подлистов.
Лицензирование
Некоторые программные продукты поставляются числом лицензий, определяемых количеством процессоров в системе, на которой они будут использоваться. Другие — числом ядер в системе. Наконец, для определения числа лицензий число процессоров может умножаться на дробный «core factor», зависящий от типа процессора!
Виртуализация
Системы виртуализации, способные моделировать многоядерные системы, могут назначить виртуальным процессорам внутри машины произвольную топологию, не совпадающую с конфигурацией реальной аппаратуры. Так, внутри хозяйской системы (1, 2, 2) некоторые известные системы виртуализации по умолчанию выносят все логические процессоры на верхний уровень, т.е. создают конфигурацию (4, 1, 1). В сочетании с особенностями лицензирования, зависящими от топологии, это может порождать забавные эффекты.
Спасибо за внимание!
Литература
- Intel Corporation. Intel® 64 and IA-32 Architectures Software Developer’s Manual. Volumes 1–3, 2014. www.intel.com/content/www/us/en/processors/architectures-software-developer-manuals.html
- Shih Kuo. Intel® 64 Architecture Processor Topology Enumeration, 2012 — software.intel.com/en-us/articles/intel-64-architecture-processor-topology-enumeration
- OSDevWiki. MADT. wiki.osdev.org/MADT
- OSDevWiki. Detecting CPU Topology. wiki.osdev.org/Detecting_CPU_Topology_%2880×86%29
Как разрабатываются и производятся процессоры: проектирование ЦП / Хабр
Теперь, когда мы знаем, как работают процессоры на высоком уровне, настало время углубиться в разбор процесса проектирования их внутренних компонентов. Это вторая статья из серии, посвящённой разработке процессоров. Рекомендую изучить для начала первую часть, чтобы вы понимать изложенные ниже концепции.
Часть 1: Основы архитектуры компьютеров (архитектуры наборов команд, кэширование, конвейеры, hyperthreading)
Часть 2: Процесс проектирования ЦП (электрические схемы, транзисторы, логические элементы, синхронизация)
Часть 3: Компонование и физическое производство чипа (VLSI и изготовление кремния)
Часть 4: Современные тенденции и важные будущие направления в архитектуре компьютеров (море ускорителей, трёхмерное интегрирование, FPGA, Near Memory Computing)
Как вы возможно знаете, процессоры и большинство других цифровых устройств состоят из транзисторов. Проще всего воспринимать транзистор как управляемый переключатель с тремя контактами. Когда затвор включён, электрический ток может течь по транзистору. Когда затвор отключён, ток течь не может. Затвор похож на выключатель света в комнате, только он гораздо меньше, быстрее и может управляться электрически.
Существует два основных типа транзисторов, используемых в современных процессорах: pMOS (PМОП) и nMOS (NМОП). nMOS-транзистор пропускает ток, когда затвор (gate) заряжен или имеет высокое напряжение, а pMOS-транзистор пропускает ток, когда затвор разряжен или имеет низкое напряжение. Сочетая эти типы транзисторов комплементарным образом, мы можем создавать логические элементы КМОП (CMOS). В этой статье мы не будем подробно разбирать особенности работы транзисторов, но коснёмся этого в третьей части серии.
Логический элемент — это простое устройство, получающее входные сигналы, выполняющее какую-то операцию, и выводящее результат. Например, элемент И (AND) включает свой выходной сигнал тогда и только тогда, когда включены все входы затвора. Инвертор, или элемент НЕ (NOT) включает свой выход, если вход отключён. Можно скомбинировать эти два затвора и получить элемент И-НЕ (NAND), который включает выход, тогда и только тогда, когда не включён ни один из входов. Существуют другие элементы со своей логической функциональностью, например ИЛИ (OR), ИЛИ-НЕ (NOR), исключающее ИЛИ (XOR) и исключающее ИЛИ с инверсией (XNOR).
Ниже показано, как из транзисторов собраны два простых элемента: инвертор и NAND. В инверторе pMOS-транзистор (сверху) соединён с питанием, а nMOS-транзистор (снизу) соединён с заземлением. На обозначении pMOS-транзисторов есть небольшой кружок, соединённый с затвором. Мы сказали, что pMOS-устройства пропускают ток, когда вход отключен, а nMOS-устройства пропускают ток, когда вход включен, поэтому легко заметить, что сигнал на выходе (Out) будет всегда противоположным сигналу на входе (In). Взглянув на элемент NAND, мы видим, что для него требуется четыре транзистора, и что выход всегда будет отключен, если выключен хотя бы один из входов. Соединение подобным образом транзисторов для образования простых сетей — это тот же процесс, который используется для проектирования более сложных логических элементов и других схем внутри процессоров.
Строительные блоки в виде логических элементов так просты, что трудно понять, как они превращаются в функционирующий компьютер. Процесс проектирования заключается в комбинировании нескольких элементов для создания небольшого устройства, способного выполнять простую функцию. Затем можно объединить множество таких устройств, чтобы создать нечто, выполняющее более сложную функцию. Процесс комбинирования отдельных компонентов для создания работающей структуры — это именно тот процесс, который используется сегодня для создания современных чипов. Единственное отличие заключается в том, что современный чип состоит из миллиардов транзисторов.
В качестве небольшого примера давайте возьмём простой сумматор — 1-битный полный сумматор. Он получает три входных сигнала — A, B, и Carry-In (входной сигнал переноса), и создаёт два выходных сигнала — Sum (сумма) и Carry-Out (выходной сигнал переноса). В простейшей схеме используется пять логических элементов, и их можно соединить вместе для создания сумматора любого размера. В современных схемах этот процесс усовершенствован оптимизацией части логики и сигналов переноса, но фундаментальные основы остаются теми же.
Выход Sum равен или A, или B, но никогда обоим, или есть входящий сигнал переноса, и тогда A и B или оба включены, или оба выключены. Выходной сигнал переноса немного сложнее. Он активен, когда или A и B включены одновременно, или есть Carry-in и один из A или B включен. Чтобы соединить несколько 1-битных сумматоров для создания более широкого сумматора, нам просто нужно соединить Carry-out предыдущего бита с Carry-in текущего бита. Чем сложнее становятся схемы, тем запутанней получается логика, но это самый простой способ сложения двух чисел. В современных процессорах используются более изощрённые сумматоры, но их схемы слишком сложны для подобного обзора. Кроме сумматоров процессоры также содержат устройства для деления, умножения и версий всех этих операций с плавающей точкой.
Подобное объединение последовательностей элементов для выполнения некой функции над входными сигналами называется комбинаторной логикой. Однако это не единственный тип логики, используемый в компьютерах. Не будет особой пользы, если мы не сможем хранить данные или отслеживать состояние. Для того, чтобы иметь возможность сохранять данные, нам нужна секвенциальная логика.
Секвенциальная логика строится аккуратным соединением инверторов и других логических элементов так, чтобы их выходы передавали сигналы обратной связи на вход элементов. Такие контуры обратной связи используются для хранения одного бита данных и называются статическим ОЗУ (Static RAM), или SRAM. Эта память называется статическим ОЗУ в противовес динамической (DRAM), потому что сохраняемые данные всегда напрямую соединены с положительным напряжением или заземлением.
Стандартный способ реализации одного бита SRAM — это показанная ниже схема из 6 транзисторов. Самый верхний сигнал, помеченный как WL (Word Line) — это адрес, и когда он включен, то данные, хранящиеся в этой 1-битной ячейке передаются в Bit Line, помеченную как BL. Выход BLB называется Bit Line Bar; это просто инвертированное значение Bit Line. Вы должны узнать два типа транзисторов и понять, что M3 с M1, как и M4 с M2, образуют инвертор.
SRAM используется для построения сверхбыстрых кэшей и регистров внутри процессоров. Эта память очень стабильна, но для хранения каждого бита данных требует от шести до восьми транзисторов. Поэтому по сравнению с DRAM она чрезвычайно затратна с точки зрения стоимости, сложности и площади на чипе. С другой стороны, Dynamic RAM хранит данные в крошечном конденсаторе, а не использует логические элементы. Она называется динамической, потому что напряжение на конденсаторе может значительно изменяться, так как он не подключён к питанию или заземлению. Есть только один транзистор, используемый для доступа к хранящимся в конденсаторе данным.
Поскольку DRAM требует всего по одному транзистору на бит и очень масштабируема, её можно плотно и дёшево упаковывать. Недостаток DRAM заключается в том, что заряд конденсатора так мал, что его необходимо постоянно обновлять. Именно поэтому после отключения питания компьютера все конденсаторы разряжаются и данные в ОЗУ теряются.
Такие компании, как Intel, AMD и Nvidia, не публикуют схем работы своих процессоров, поэтому невозможно показать подобных полных электрических схем для современных процессоров. Однако этот простой сумматор позволит вам получить представление о том, что даже самые сложные части процессора можно разбить на логические и запоминающие элементы, а затем и на транзисторы.
Теперь, когда мы знаем, как производятся некоторые компоненты процессора, нам нужно разобраться, как соединить всё вместе и синхронизировать. Все ключевые компоненты процессора подключены к синхронизирующему (тактовому) сигналу (clock signal). Он попеременно имеет высокое и низкое напряжение, меняя его с заданным интервалом, называемым частотой (frequency). Логика внутри процессора обычно переключает значения и выполняет вычисления, когда синхронизирующий сигнал меняет напряжение с низкого на высокое. Синхронизируя все части, мы можем гарантировать, что данные всегда поступают в правильное время, чтобы в процессоре не возникали «глюки».
Вы могли слышать, что для повышения производительности процессора можно увеличить частоту тактовых сигналов. Это повышение производительности происходит благодаря тому, что переключение транзисторов и логики внутри процессора начинает происходить чаще, чем предусмотрено. Поскольку в секунду происходит больше циклов, то можно выполнить больше работы и процессор будет иметь повышенную производительность. Однако это справедливо до определённого предела. Современные процессоры обычно работают с частотой от 3,0 ГГц до 4,5 ГГц, и эта величина почти не изменилась за последние десять лет. Точно так же, как металлическая цепь не прочнее её самого слабого звена, процессор может работать не быстрее его самой медленной части. К концу каждого тактового цикла каждый элемент процессора должен завершить свою работу. Если какие-то части ещё её не завершили, то тактовый сигнал слишком быстрый и процессор не будет работать. Проектировщики называют эту самую медленную часть критическим путём (Critical Path) и именно он определяет максимальную частоту, с которой может работать процессор. Выше определённой частоты транзисторы просто не успевают достаточно быстро переключаться и начинают глючить или выдавать неверные выходные значения.
Повысив напряжение питания процессора, мы можем ускорить переключение транзисторов, но это тоже срабатывает до определённого предела. Если подать слишком большое напряжение, то мы рискуем сжечь процессор. Когда мы повышаем частоту или напряжение процессора, он всегда начинает излучать больше тепла и потреблять бОльшую мощность. Так происходит потому, что мощность процессора прямо пропорциональна частоте и пропорциональна квадрату напряжения. Чтобы определить энергопотребление процессора, мы рассматриваем каждый транзистор как маленький конденсатор, который нужно заряжать или разряжать при изменении его значения.
Подача питания — это настолько важная часть процессора, что в некоторых случаях до половины физических контактов на чипе может использоваться только для питания или заземления. Некоторые чипы при полной нагрузке могут потреблять больше 150 амперов, и со всем этим током нужно управляться чрезвычайно аккуратно. Для сравнения: центральный процессор генерирует больше тепла на единицу площади, чем ядерный реактор.
Тактовый сигнал в современных процессорах отнимает примерно 30-40% от его общей мощности, потому что он очень сложен и должен управлять множеством различных устройств. Для сохранения энергии большинство процессоров с низким потреблением отключает части чипа, когда они не используются. Это можно реализовать отключением тактового сигнала (этот способ называется Clock Gating) или отключением питания (Power Gating).
Тактовые сигналы создают ещё одну сложность при проектировании процессора: поскольку их частоты постоянно растут, то на работу начинают влиять законы физики. Даже несмотря на чрезвычайно высокую скорость света, она недостаточно велика для высокопроизводительных процессоров. Если подключить тактовый сигнал к одному концу чипа, то ко времени, когда сигнал достигнет другого конца, он будет рассинхронизован на значительную величину. Чтобы синхронизировать все части чипа, тактовый сигнал распределяется при помощи так называемого H-Tree. Это структура, гарантирующая, что все конечные точки находятся на совершенно одинаковом расстоянии от центра.
Может показаться, что проектирование каждого отдельного транзистора, тактового сигнала и контакта питания в чипе — чрезвычайно монотонная и сложная задача, и это в самом деле так. Даже несмотря на то, что в таких компаниях, как Intel, Qualcomm и AMD, работают тысячи инженеров, они не смогли бы вручную спроектировать каждый аспект чипа. Для проектирования чипов такого масштаба они используют множество сложных инструментов, автоматически генерирующих конструкции и электрические схемы. Такие инструменты обычно получают высокоуровневое описание того, что должен делать компонент, и определяют наилучшую аппаратную конфигурацию, удовлетворяющую этим требованиям. Недавно возникло направление развития под названием High Level Synthesis, которое позволяет разработчикам указывать необходимую функциональность в коде, после чего компьютеры определяют, как оптимальнее достичь её в оборудовании.
Точно так же, как вы можете описывать компьютерные программы через код, проектировщики могут описывать кодом аппаратные устройства. Такие языки, как Verilog и VHDL позволяют проектировщикам оборудования выражать функциональность любой создаваемой ими электрической схемы. После выполнения симуляций и верификации таких проектов их можно синтезировать в конкретные транзисторы, из которых будет состоять электрическая схема. Хоть этап верификации может и не кажется таким увлекательным, как проектирование нового кэша или ядра, он значительно важнее их. На каждого нанимаемого компанией инженера-проектировщика может приходиться пять или более инженеров по верификации.
Верификация нового проекта часто занимает больше времени и денег, чем создание самого чипа. Компании тратят так много времени и средств на верификацию, потому что после отправки чипа в производство его невозможно исправить. В случае ошибки в ПО можно выпустить патч, но оборудование работает иначе. Например, компания Intel обнаружила баг в модуле деления с плавающей запятой некоторых чипов Pentium, и в результате это вылилось в потери, эквивалентные современным 2 миллиардам долларов.
Сложно осмыслить то, что в одном чипе может быть несколько миллиардов транзисторов и понять, что все они делают. Если разбить чип на его отдельные внутренние компоненты, становится немного легче. Из транзисторов составляются логические элементы, логические элементы комбинируются в функциональные модули, выполняющие определённую задачу, а эти функциональные модули соединяются вместе, образуя архитектуру компьютера, которую мы обсуждали в первой части серии.
БОльшая часть работ по проектированию автоматизирована, но изложенное выше позволяет нам осознать, насколько сложен только что купленный нами новый ЦП.
Во второй части серии я рассказал о процессе проектирования ЦП. Мы обсудили транзисторы, логические элементы, подачу питания и синхронизирующих сигналов, синтез конструкции и верификацию. В третьей части мы узнаем, что требуется для физического производства чипа. Все компании любят хвастаться тем, насколько современен их процесс изготовления (Intel — 10-нанометровый, Apple и AMD — 7-нанометровый, и т.д.), но что же на самом деле означают эти числа? Об этом мы расскажем в следующей части.
Рекомендуемое чтение
Я не знал, как работают процессоры, поэтому написал программный симулятор / Хабр
Несколько месяцев назад меня вдруг поразила мысль, что я понятия не имею о принципах работы компьютерного железа. Я до сих пор не знаю, как работают современные компьютеры.
Я прочитал книгу «Но откуда он знает?» Кларка Скотта с детальным описанием простого 8-битного компьютера: начиная с логических вентилей, ОЗУ, транзисторов процессора, заканчивая арифметико-логическим устройством и операциями ввода-вывода. И мне захотелось реализовать всё это в коде.
Хотя я не настолько интересуюсь физикой микросхем, но книга просто скользит по волнам и красиво объясняет электросхемы и как биты перемещаются по системе — от читателя не требуется знание электротехники. Но мне недостаточно текстового описания. Я должен видеть вещи в действии и учиться на своих неизбежных ошибках. Так я начал реализацию схем в коде. Путь оказался тернист, но поучителен.
Результат моей работы можно посмотреть в репозитории simple-computer: простом вычислителе. Он простой и он вычисляет.
Пример программ
Код процессора реализован как ужасная куча логических вентилей, которые включаются и выключаются, но он работает. Я прогнал модульные тесты, а все мы знаем, что модульные тесты — неопровержимое доказательство, что программа работает.
Код обрабатывает ввод с клавиатуры и отображает текст на дисплее, используя кропотливо созданный набор глифов для профессионального шрифта, который я назвал Daniel Code Pro. Единственный чит: чтобы взять ввод с клавиатуры и вывести результат, мне пришлось подключить каналы через GLFW, но в остальном это полностью программная симуляция электросхемы.
Я даже написал грубый ассемблер, который на многое открыл глаза, мягко говоря. Он не идеален. На самом деле даже немного дерьмовый, но он показал мне проблемы, которые другие люди уже решили много-много лет назад.
«Тринадцатилетние дети собирают процессоры в Minecraft. Позови, когда сможешь сделать настоящий CPU из телеграфных реле»
Моя ментальная модель устройства CPU застряла на уровне учебников по информатике для начинающих. Процессор для эмулятора Gameboy, который я написал в 2013 году, на самом деле не похож на современные CPU. Даже если эмулятор — это просто конечный автомат (машина состояний), он не описывает состояния на уровне логических вентилей. Почти всё можно реализовать с помощью только оператора switch
и сохраняя состояние регистров.
Я хочу лучше разобраться, как всё устроено, потому что не знаю, например, что такое кэш L1/L2 и конвейеризация и я не совсем уверен, что понимаю статьи об уязвимостях Meltdown и Spectre. Кто-то сказал, что они оптимизируют код таким образом, чтобы использовать кэш процессора, но я не знаю, как это проверить, кроме как поверить на слово. Я не совсем уверен, что означают все инструкции x86. Не понимаю, как люди отправляют задачи на GPU или TPU. И вообще, что такое TPU? Я не знаю, как использовать SIMD-инструкции.
Всё это построено на фундаменте, который нужно усвоить в первую очередь. Это значит вернуться к основам и сделать что-то простое. В вышеупомянутой книге Кларка Скотта описан простейший компьютер. Вот почему я начал с него.
Компьютер Скотта — это 8-разрядный процессор, подключённый к 256 байтам ОЗУ, все они подключены через 8-разрядную системную шину. У него 4 регистра общего назначения и 17 машинных инструкций. Кто-то сделал визуальный симулятор для веба: это действительно здорово. Страшно подумать, сколько времени потребовалось, чтобы отследить все состояния схемы!
Схема со всеми компонентам процессора Скотта. Копирайт 2009-2016. Зигберт Фильбингер и Джон Кларк Скотт
Книга сопровождает вас по маршруту от скромных логических вентилей до битов в памяти и регистров, а затем продолжает наслаивать компоненты, пока вы не получите что-то похожее на схему выше. Очень рекомендую прочитать книгу, даже если вы уже знакомы с концепциями. Только не версию Kindle, потому что диаграммы иногда трудно увеличить и разобрать на экране «читалки». По-моему, это многолетняя проблема Kindle.
Мой компьютер отличается от версии Скотта разве что тем, что я обновил его до 16 бит, чтобы увеличить объём доступной памяти, ведь хранение только глифов для таблицы ASCII занимает большую часть 8-битной машины Скотта, оставляя совсем мало места для полезного кода.
В целом, разработка шла по такой схеме: чтение текста, изучение диаграмм, а затем попытка реализовать их на языке программирования общего назначения и определённо не использовать никаких специализированных инструментов для проектирования интегральных схем. Я написал симулятор на Go просто потому, что немного знаком с этим языком. Скептики могут сказать: «Болван! Неужели ты не мог изучить VHDL или Verilog, или LogSim, или ещё что-то. Но к тому моменту я уже написал свои биты, байты и логические вентили и погрузился слишком глубоко. Может, в следующий раз я выучу эти языки и пойму, сколько времени потратил впустую, но это мои проблемы.
В большой схеме в компьютере просто передаётся куча булевых значений, поэтому подходит любой язык, который дружит с булевой алгеброй.
Наложение схемы на эти булевы значения помогает нам (программистам) вывести смысл, а самое главное — решить, какой порядок байтов будет использовать система, и убедиться, что все компоненты передают данные по шине в правильном порядке.
Это было очень трудно реализовать. Ради смещения я выбрал представление с обратным порядком байтов, но при тестировании ALU никак не мог понять, почему выходят неправильные цифры. Мой кот услышал много, очень много непечатных выражений.
Разработка шла не быстро: возможно, она заняла около месяца-двух моего свободного времени. Но когда только процессор успешно выполнил операцию , я был на седьмом небе от счастья.
Всё шло своим чередом, пока дело не дошло до ввода-вывода. Книга предлагала дизайн системы с простой клавиатурой и интерфейсом дисплея, чтобы вводить данные в машину и выводить результат. Ну, мы уже зашли так далеко, нет смысла останавливаться на полпути. Я поставил цель реализовать набор на клавиатуре и отображение букв на дисплее.
В качестве аппаратного интерфейса между CPU и внешним миром периферийные устройства используют шаблон адаптера. Наверное, несложно догадаться, что этот шаблон позаимствован из проектирования программного обеспечения.
Как адаптеры ввода-вывода подключаются к окну GLFW
С таким разделением оказалось довольно просто подключить клавиатуру и дисплей к окну под управлением GLFW. На самом деле я просто вытащил большую часть кода из своего эмулятора и немного изменил его, чтобы каналы Go работали как сигналы ввода/вывода.
Вероятно, это самая сложная часть, по крайней мере, самая громоздкая. Трудно писать на ассемблере с таким ограниченным набором инструкций, а на моём грубом ассемблере ещё хуже, потому что вы не можете обматерить никого, кроме себя.
Самой большой проблемой стало жонглирование четырьмя регистрами, отслеживать их, вытаскивая данные из регистров и временно сохраняя их в памяти. В процессе я вспомнил, что у процессора Gameboy есть регистр указателя стека для удобства выгрузки и загрузки регистров. К сожалению, у этого компьютера нет такой роскоши, поэтому приходилось постоянно вручную перемещать данные в память и обратно.
Я решил потратить время только на одну псевдоинструкцию CALL
, чтобы вызвать функцию, а затем вернуться к точке. Без этого доступны вызовы только на один уровень в глубину.
Кроме того, поскольку машина не поддерживает прерывания, пришлось реализовать ужасный код опроса состояния клавиатуры. В книге обсуждаются шаги, необходимые для реализации прерываний, но это серьёзно усложняет схему.
Но хватить ныть, я всё-таки написал четыре программы, и большинство из них используют какой-то общий код для рендеринга шрифтов, ввода с клавиатуры и т. д. Это не совсем операционная система, но даёт понимание, что делает простая ОС.
Это было нелегко. Самая сложная часть программы text-writer — правильно рассчитать, когда перейти к новой строке или что происходит, когда вы нажимаете клавишу Enter.
main-getInput:
CALL ROUTINE-io-pollKeyboard
CALL ROUTINE-io-drawFontCharacter
JMP main-getInput
Основной цикл программы text-writer
Я не удосужился реализовать клавишу Backspace и клавиши-модификаторы. Зато понял, сколько труда требует разработка текстовых редакторов и насколько это утомительно.
Это был весёлый и очень полезный для меня проект. В разгар программирования на ассемблере я почти забыл о логических вентилях, работающих внизу. Я поднялся на верхние уровни абстракции.
Хотя этот процессор очень прост и далёк от CPU в моём ноутбуке, но мне кажется, что проект многому меня научил, в частности:
- Как биты перемещаются по шине между всеми компонентами.
- Как работает простой ALU.
- Как выглядит простой цикл Fetch-Decode-Execute.
- Что машина без регистра указателя стека и концепции стека — отстой.
- Что машина без прерываний тоже отстой.
- Что такое ассемблер и что он делает.
- Как периферийные устройства взаимодействуют с простым процессором.
- Как работают простые шрифты и как отображать их на дисплее.
- Как может выглядеть простая операционная система.
Так что дальше? В книге говорится, что никто не производил таких компьютеров с 1952 года. Это значит, что мне придётся изучить материал за последние 67 лет. Это займёт меня на какое-то время. Я вижу, что руководство по x86 составляет 4800 страниц: вполне достаточно для приятного, лёгкого чтения перед сном.
Может, я немного побалуюсь с операционной системой, языком C, убью вечер с набором для сборки PiDP-11 и паяльником, а потом заброшу это дело. Не знаю, посмотрим.
Если серьёзно, то я думаю исследовать архитектуру RISC, возможно, RISC-V. Вероятно, лучше начать с ранних процессоров RISC, чтобы понять их происхождение. У современных процессоров гораздо больше функций: кэши и прочее, я хочу разобраться в них. Там нужно многое изучить.
Пригодятся ли эти знания на моей основной работе? Возможно, пригодятся, хотя вряд ли. В любом случае, мне это нравится, так что неважно. Спасибо за чтение!
Как работает процессор?
Компьютерный процессор обычно называют ЦП или центральным процессором компьютера. Процессор — это основной компонент компьютера, предназначенный для перемещения и обработки данных. Компьютерные процессоры обычно называют скоростью, с которой ЦП может обрабатывать компьютерные инструкции в секунду, измеряемой в герцах, и являются одним из основных аргументов в пользу компьютера.
Как работает процессор?
Компьютерный процессор действует как основной координирующий компонент компьютера.ЦП будет получать доступ к программам, данным или другим функциям компьютера из ОЗУ (оперативной памяти) при вызове операционной системы компьютера. Затем процессор будет интерпретировать компьютерные инструкции, относящиеся к заказанной задаче, перед тем, как отправить ее обратно в ОЗУ компьютера для выполнения через системную шину компьютера в правильном порядке выполнения.
Логика компьютерного процессора
В основе процессора компьютера лежит его способность обрабатывать код машинного языка.ЦП может выполнять три основные инструкции машинного языка:
— Перенос данных из одного места в памяти компьютера в другое
— переход к новым наборам инструкций на основе логических операций или вариантов выбора
— Выполнять математические операции с помощью арифметико-логического устройства (ALU)
Для выполнения этих операций процессор использует адресную шину, которую он использует для отправки адресов в память компьютера, а также шину данных, которая используется для получения или отправки информации в память компьютера.Он также имеет отдельную линию управления, которая будет уведомлять память компьютера, если он получает или отправляет / устанавливает заданную ячейку памяти. Для выполнения всех запланированных операций ЦП также имеет часы, которые служат основой для синхронизации действий процессора с остальной частью компьютера. Для доступа к часто используемым компьютерным инструкциям или данным процессоры также будут реализовывать различные схемы кэширования, чтобы получить доступ к требуемым данным с большей скоростью, чем при использовании ОЗУ прямого доступа.
Память процессора
Процессор компьютера использует постоянную память и оперативную память (соответственно, ROM и RAM). ПЗУ процессора запрограммировано с предварительно установленной информацией, которая постоянно запрограммирована с базовыми функциями для обеспечения связи процессора с шиной данных. ПЗУ обычно называют BIOS (базовая система ввода / вывода) на компьютерах с Windows, а также используется для получения загрузочного сектора компьютера.
Процессор может читать и записывать в ОЗУ в зависимости от того, какое действие (я) текущий набор команд определил, нужно ли процессору выполнить.Оперативная память не предназначена для постоянного сохранения данных и отключается, когда компьютер выключается или теряет питание.
Роль 64-битного процессора
Хотя 64-битные компьютерные процессоры были развернуты с начала 1990-х годов, в последние годы они были развернуты в большом количестве только на уровне потребителей. Все основные производители компьютерных процессоров в настоящее время производят 64-битные компьютерные процессоры, которые доступны для использования в различных типах операционных систем.Основное преимущество 64-битного компьютерного процессора перед устаревшими конструкциями — это значительно расширенное адресное пространство, доступное процессору. Предыдущие 32-битные процессоры были ограничены максимумом от двух до четырех гигабайт эффективного доступа к оперативной памяти. 64-гигабайтные процессоры также могут обеспечить расширенный доступ к жестким дискам и видеокарте компьютера, что помогает еще больше повысить общую производительность системы.
Ранние пользователи 64-битных процессоров не обязательно увидят высокую производительность системы, если не будут выполнять высокоточные задачи, такие как редактирование видео или игры в сетевые 3D-видеоигры.Это будет и дальше меняться, поскольку все больше приложений предназначены для использования преимуществ 64-битных процессоров и увеличения объема памяти новых компьютерных процессоров.
.
Как работают процессоры | PC Gamer
Углубленное изучение того, что дает вашему компьютеру интеллектуальную мощь
На вопрос о том, как работает центральный процессор, вы можете сказать, что это мозг компьютера. Он выполняет все вычисления по математике и принимает логические решения на основе определенных результатов. Однако, несмотря на то, что современные высокопроизводительные процессоры созданы на основе миллиардов транзисторов, они по-прежнему состоят из основных компонентов и основы. Здесь мы рассмотрим то, что происходит в большинстве процессоров, и основы, на которых они построены.
Этот рисунок представляет собой блок-схему архитектуры Intel Nehalem, которую мы можем использовать для получения общего обзора. Хотя мы не будем вдаваться в подробности этой конкретной конструкции (некоторые из них характерны для процессоров Intel), то, что мы рассмотрим, действительно объясняет большую часть того, что происходит.
Hard Stuff: компоненты процессора
Большинство современных процессоров содержат следующие компоненты:
- Блок управления памятью, который обрабатывает преобразование адресов памяти и доступ к ней
- Сборщик инструкций, который захватывает инструкции из памяти
- Инструкция декодер, который превращает инструкции из памяти в команды, которые понимает процессор.
- Блоки выполнения, которые выполняют операцию; по крайней мере, процессор будет иметь арифметический и логический блок (ALU), но также может быть включен блок с плавающей запятой (FPU).
- Регистры, которые представляют собой небольшие биты памяти для хранения важных битов данных
Блок управления памятью, сборщик инструкций и декодер инструкций образуют так называемый интерфейс.Это пережиток старых дней вычислительной техники, когда интерфейсные процессоры считывали перфокарты и превращали их содержимое в ленточные катушки, на которых работал настоящий компьютер. Блоки исполнения и регистры образуют серверную часть.
Блок управления памятью (MMU)
Основная задача блока управления памятью — преобразовать адреса из виртуального адресного пространства в физическое адресное пространство. Виртуальное адресное пространство позволяет системе убедить программы в том, что все возможное адресное пространство доступно, даже если физически это не так.Например, в 32-битной среде система считает, что имеет 4 ГБ адресного пространства, даже если установлено только 2 ГБ ОЗУ. Это сделано для упрощения программирования, поскольку программист не знает, на какой системе будет выполняться приложение.
Другая задача блока управления памятью — защита доступа. Это предотвращает чтение или запись приложением адреса памяти другого приложения без прохождения надлежащих каналов.
Сборщик и декодер инструкций
Как следует из названия, эти устройства захватывают инструкции и декодируют их в операции.Примечательный в современных проектах x86, декодер превращает инструкции в микрооперации, с которыми будут работать следующие этапы. В современных процессорах то, что обрабатывается в декодере, обычно поступает в блок управления, который определяет наилучший способ выполнения инструкций. Некоторые из используемых методов включают прогнозирование ветвлений, которое пытается выяснить, что будет выполнено, если ветвление должно произойти, и выполнение вне очереди, которое перестраивает инструкции таким образом, чтобы они выполнялись наиболее эффективным способом.
Execution Units
Минимум, который будет иметь универсальный процессор, — это арифметический и логический блок (ALU). Этот исполнительный блок работает только с целочисленными значениями и выполняет следующие операции:
- Сложение и вычитание; умножение выполняется путем повторных сложений, а деление приближается к повторяющимся вычитаниям (здесь есть хорошая статья по этой теме)
- Логические операции, такие как OR, AND, NOT и XOR
- Битовый сдвиг, который перемещает цифры влево или вправо
Многие процессоры также включают модуль с плавающей запятой (FPU).Это позволяет процессору работать с большим диапазоном и более высокой точностью чисел, которые не являются целыми. Поскольку FPU сложны, часто достаточно, чтобы быть их собственным процессором, они часто исключаются на меньших процессорах с низким энергопотреблением.
Регистры
Регистры — это небольшие биты памяти, которые содержат непосредственно важные данные. Обычно их немного, и они могут хранить данные, равные размеру битов, для которого был создан процессор. Таким образом, 32-битный процессор обычно имеет 32-битные регистры.
Самыми распространенными регистрами являются: регистры, в которых хранится результат операции, счетчик программ (указывает, где находится следующая инструкция) и слово состояния или код условия (который определяет ход выполнения программы).В некоторых архитектурах есть специальные регистры для облегчения работы. Например, Intel 8086 имеет регистры сегмента и смещения. Они будут использоваться для определения адресных пространств в архитектуре отображения памяти 8086.
Примечание о битах
Биты на процессоре обычно относятся к самому большому размеру данных, который он может обработать за один раз. В основном это относится к исполнительному блоку. Однако это не означает, что процессор ограничен только обработкой данных такого размера. Восьмиразрядный процессор по-прежнему может обрабатывать 16-битные и 32-битные числа, но для этого требуется как минимум две и четыре операции соответственно.
Мягкие материалы: идеи и разработки в процессорах
За годы компьютерного дизайна воплощалось все больше и больше идей и разработок. Они были разработаны с целью повышения эффективности процессора в том, что он делает, за счет увеличения количества инструкций за такт (IPC).
Дизайн набора команд
Наборы команд сопоставляют числовые индексы команд в процессоре. Эти команды могут быть такими простыми, как сложение двух чисел, или такими сложными, как инструкция SSE RSQRTPS (как описано в файле справки: «Вычислить обратные квадратные корни для упакованных значений с плавающей запятой одинарной точности»).
На заре компьютеров память была очень медленной, и ее было не так много, процессоры становились быстрее, а программы — сложнее. Чтобы сэкономить как на доступе к памяти, так и на размере программы, наборы инструкций были разработаны с учетом следующих идей:
- Инструкции переменной длины, чтобы более простые операции могли занимать меньше места
- Выполнение большого количества команд адресации памяти
- Операции могут выполняться в самих ячейках памяти в дополнение к использованию регистров или как часть инструкции.
По мере роста производительности памяти компьютерные ученые обнаружили, что было быстрее разбивать сложные операции на более простые.Инструкции также можно упростить, чтобы ускорить процесс декодирования. Это привело к появлению идеи дизайна вычислений с сокращенным набором команд (RISC). Уменьшение в этом случае означает сокращение времени на выполнение инструкции. Старый способ был задним числом назван Computing Set Instruction Set Computing (CISC). Подводя итог идеям RISC:
- Единая длина инструкции для упрощения декодирования
- Меньшее количество простых команд адресации памяти
- Операции могут выполняться только с данными в регистрах или как часть инструкции
Были и другие попытки при проектировании набора команд.Одним из них является очень длинное служебное слово (VLIW). VLIW объединяет несколько независимых инструкций в один модуль, который будет запускаться на нескольких исполнительных модулях. Одним из самых больших препятствий является то, что компилятор требует от компилятора сортировки инструкций заранее, чтобы максимально использовать аппаратное обеспечение, а большинство программ общего назначения не справляются сами с собой. VLIW использовался в Intel Itanium, Transmeta Crusoe, MCST Elbrus, AMD TeraCore и NVIDIA Project Denver (вроде, у него схожие характеристики)
Многозадачность
Раньше компьютеры могли делать только одну вещь за раз и один раз оно будет работать, оно будет продолжаться до завершения или до тех пор, пока не возникнет проблема с программой.По мере того, как системы становились более мощными, родилась идея под названием «разделение времени». При разделении времени система будет работать над одной программой, и если что-то блокирует ее продолжение, например, ожидание готовности периферийного устройства, система сохранит состояние программы в памяти, а затем перейдет к другой программе. В конце концов, он вернется к заблокированной программе и увидит, есть ли у нее то, что нужно для запуска.
Разделение времени выявило проблему: программа могла несправедливо перегрузить систему либо потому, что программа действительно имела долгое время выполнения, либо потому, что где-то зависала.Итак, следующие системы были построены таким образом, чтобы они работали над программами в отрезки времени. То есть, каждая программа запускается в течение определенного времени, и после того, как временной интервал истек, она автоматически переходит к другой программе. Если интервалы времени достаточно малы, создается впечатление, что компьютер выполняет несколько задач одновременно.
Одной из важных функций, которая действительно помогла многозадачности, является система прерываний. Благодаря этому процессору не нужно постоянно опрашивать программы или устройства, есть ли у них что-то готовое; программа или устройство могут генерировать сигнал, чтобы сообщить процессору, что они готовы.
Кэширование
Кэш — это память в процессоре, которая, несмотря на небольшой размер, гораздо быстрее доступна, чем ОЗУ. Идея кэширования заключается в том, что в нем хранятся часто используемые данные и инструкции, которые помечаются своими адресами в памяти. MMU сначала просматривает кеш, чтобы увидеть, есть ли в нем то, что он ищет. Чем больше раз осуществляется доступ к данным, тем ближе время доступа к кэш-памяти, что увеличивает скорость выполнения.
Обычно данные могут находиться только в одном месте кэша.Метод увеличения вероятности нахождения данных в кеше известен как ассоциативность. Двусторонний ассоциативный кеш означает, что данные могут быть в двух местах, четырехсторонний означает, что они могут быть в четырех, и так далее. Хотя может иметь смысл разрешить данные просто находиться в любом месте кеша, это также увеличивает время поиска, что может свести на нет преимущества кеширования.
Конвейерная обработка
Конвейерная обработка — это способ для процессора увеличить пропускную способность инструкций путем имитации работы сборочных линий. Рассмотрим этапы выполнения инструкции:
- Команда выборки (IF)
- Команда декодирования (ID)
- Команда выполнения (EX)
- Доступ к памяти (MEM)
- Запись результатов обратно (WB)
Ранние компьютеры будет обрабатывать каждую инструкцию полностью через эти шаги перед обработкой следующей инструкции, как показано здесь:
За 10 тактов процессор полностью завершает работу двумя инструкциями.Конвейерная обработка позволяет запускать следующую инструкцию, как только текущая выполняется с шагом. На следующей диаграмме показана конвейерная обработка в действии:
За те же 10 тактовых циклов полностью обрабатываются шесть инструкций, что увеличивает пропускную способность в три раза.
Прогнозирование переходов
Основная проблема конвейерной обработки заключается в том, что если необходимо выполнить какое-либо ветвление, то инструкции, которые обрабатывались на более ранних этапах, должны быть отброшены, поскольку они больше не будут обрабатываться.Давайте посмотрим на ситуацию, когда это происходит.
Инструкция CMP — это инструкция сравнения, например, x = y? Это устанавливает флаг результата в процессоре. Инструкция BNE — это «ветвь, если не равно», которая проверяет этот флаг. Если x не равно y, то процессор переходит в другое место в программе. Следующие инструкции (SUB, MUL и DIV) следует отбросить, потому что они больше не будут выполняться. Это создает промежуток в пять тактов перед обработкой следующей инструкции.
Цель предсказания ветвления — угадать, какие инструкции будут выполнены. Для этого существует несколько алгоритмов, но общая цель — свести к минимуму количество раз, которое конвейер должен очищать из-за того, что произошла ветвь.
Выполнение вне очереди
Выполнение вне очереди — это способ для процессора изменить порядок инструкций для эффективного выполнения. Возьмем, к примеру, программу, которая делает это:
- x = 1
- y = 2
- z = x + 3
- foo = z + y
- bar = 42
- напечатайте «hello world!»
Допустим, исполнительный блок может обрабатывать две инструкции одновременно.Затем эти инструкции выполняются следующим образом:
- x = 1, y = 2
- z = x + 3
- foo = z + y
- bar = 42, выведите «hello world!»
Поскольку значение «foo» зависит от «z», эти две инструкции не могут выполняться одновременно. Однако, изменив порядок инструкций:
- x = 1, y = 2
- z = x + 3, bar = 42
- foo = z + y, выведите «hello world!»
Таким образом можно избежать лишнего цикла.Однако реализация выполнения вне очереди является сложной задачей, и приложение по-прежнему ожидает, что инструкции будут обрабатываться в исходном порядке. Обычно это предотвращает нарушение порядка выполнения процессорами для мобильных устройств и небольшой электроники, поскольку дополнительное энергопотребление перевешивает его преимущества в производительности, но последние мобильные процессоры на базе ARM включают это, потому что теперь верно обратное.
Сложная машина, состоящая из простых частей
Если смотреть с чисто аппаратной точки зрения, процессор может показаться довольно сложным.В действительности, те миллиарды транзисторов, которые используются сегодня в современных процессорах, все еще можно разбить на простые части или идеи, которые закладывают основу работы процессоров. Если после прочтения этой статьи у вас останется больше вопросов, чем ответов, лучше всего начать изучать больше — это индекс Википедии по технологиям ЦП.
.
Как работает процессор процессора? | Small Business
Каждое вычислительное устройство, от простых игрушек до крупных бизнес-систем, имеет важный компонент, называемый центральным процессором. ЦП выполняет вычисления, выполняет логические сравнения и перемещает данные до миллиардов раз в секунду. Он работает, выполняя простые инструкции по одной за раз, запускаемые главным сигналом синхронизации, который запускает весь компьютер.
Описание
Процессор ЦП — это компьютерная микросхема размером со спичечный коробок.Внутри корпуса находится кремниевый прямоугольник, содержащий миллионы транзисторных схем. Из устройства выступают десятки металлических штифтов, каждый из которых передает электронные сигналы в микросхему и из нее. Микросхема подключается к разъему на печатной плате компьютера и обменивается данными с памятью, жесткими дисками, экранами дисплея и другими устройствами, внешними по отношению к ЦП.
Часы
Схема синхронизации, называемая часами, отправляет электрические импульсы в ЦП. В зависимости от процессора часы могут работать со скоростью от сотен тысяч до миллиардов циклов в секунду.Импульсы управляют активностью внутри ЦП; поскольку другие схемы зависят от тех же часов, он поддерживает синхронизацию сложных событий в компьютере.
Инструкции
Все процессоры имеют набор команд — список действий, выполняемых процессором, включая сложение чисел, сравнение двух частей данных и перемещение данных в CPU. Программное обеспечение, которое вы запускаете на своем компьютере, состоит из миллионов инструкций ЦП, расположенных в последовательности; инструкции — это очень простые операции, поэтому ЦП выполняет многие из них для выполнения значимых задач.Некоторые семейства процессоров, например те, которые используются в настольных ПК, используют один и тот же набор инструкций, что позволяет им запускать одно и то же программное обеспечение. ЦП вне семейства продуктов могут использовать другие инструкции; Например, процессор iPad имеет другие инструкции, чем процессор на ноутбуке с Windows.
ALU
Процессоры имеют схему, называемую арифметико-логическим блоком, которая выполняет вычисления и сравнения. Большинство процессоров выполняет арифметические операции: умножение, сложение, деление и вычитание; сложная математика, такая как статистические функции, представляет собой комбинацию множества простых операций, выполняемых с высокой скоростью.ALU также выполняет логические сравнения между двумя элементами данных, чтобы определить, равны ли они или один имеет большее значение, чем другой.
Блок управления
ЦП содержит блок управления, который координирует действия других рабочих частей процессора. Блок управления разбивает каждую инструкцию на набор действий и дает указание различным подсистемам ЦП выполнять эти действия. Например, блок управления может дать команду ALU умножить два числа вместе, а затем добавить третье число к результату.
Память
Микросхема ЦП имеет ограниченный объем очень быстрой памяти. Он имеет набор областей хранения, называемых регистрами, с которыми АЛУ действует напрямую. Например, ALU может быстро добавить число в регистре 2 к содержимому регистра 1. ЦП также хранит недавно использованные инструкции и данные в области, называемой кэш-памятью, что повышает эффективность компьютера. Например, в программе, которая умножает цену на количество, ЦП ищет эти числа в своей кэш-памяти.Если он их находит, это избавляет процессор от лишней работы по извлечению чисел из микросхем памяти вне процессора.
.
Как работают микропроцессоры | HowStuffWorks
Даже невероятно простой микропроцессор, показанный в предыдущем примере, будет иметь довольно большой набор инструкций, которые он может выполнять. Набор инструкций реализован в виде битовых комбинаций, каждая из которых имеет различное значение при загрузке в регистр инструкций. Люди не особенно хорошо запоминают битовые шаблоны, поэтому для представления различных битовых шаблонов определяется набор коротких слов. Этот набор слов называется ассемблерным языком процессора.Ассемблер может очень легко преобразовать слова в их битовые комбинации, а затем выходные данные ассемблера помещаются в память для выполнения микропроцессором.
Вот набор инструкций на языке ассемблера, которые разработчик может создать для простого микропроцессора в нашем примере:
Объявление
- LOADA mem — Загрузить регистр A из адреса памяти
- LOADB mem — Загрузить регистр B из адреса памяти
- CONB con — Загрузить постоянное значение в регистр B
- SAVEB mem — Сохранить регистр B по адресу памяти
- SAVEC mem — Сохранить регистр C по адресу памяти
- ADD — Сложить A и B и сохранить результат в C
- SUB — Вычесть A и B и сохранить результат в C
- MUL — Умножить A и B и сохранить результат в C
- DIV — Разделить A и B и сохранить результат в C
- COM — Сравнить A и B и сохранить результат в тесте
- JUMP addr — Перейти к адресу
- JEQ addr — Перейти, если он равен, по адресу
- JNEQ addr — Перейти, если не равен, по адресу
- JG addr — Перейти, если больше, по адресу
- JGE addr — Перейти, если больше или равно, по адресу
- JL addr — Перейти, если меньше, по адресу
- JLE addr — Перейти, если меньше или равно адрес
- STOP — Остановить выполнение
Если вы прочитали Как работает программирование на C, то вы знаете, что этот простой фрагмент кода C вычислит факториал 5 (где факториал 5 = 5! = 5 * 4 * 3 * 2 * 1 = 120):
a = 1; f = 1; в то время как (a <= 5) {f = f * a; а = а + 1;}
В конце выполнения программы переменная f содержит факториал 5.
Язык ассемблера
Компилятор C переводит этот код C на язык ассемблера. Если предположить, что ОЗУ этого процессора начинается с адреса 128, а ПЗУ (которое содержит программу на языке ассемблера) начинается с адреса 0, тогда для нашего простого микропроцессора язык ассемблера может выглядеть так:
// Предположим, что a находится по адресу 128 // Предположим, что F находится по адресу 1290 CONB 1 // a = 1; 1 SAVEB 1282 CONB 1 // f = 1; 3 SAVEB 1294 LOADA 128 // если a> 5, переход к 175 CONB 56 COM7 JG 178 LOADA 129 // f = f * a; 9 LOADB 12810 MUL11 SAVEC 12912 LOADA 128 // a = a + 1; 13 CONB 114 ADD15 SAVEC 12816 JUMP 4 // возврат к if17 STOP
ROM
Итак, теперь вопрос: «Как все эти инструкции выглядят в ПЗУ?» Каждая из этих инструкций на языке ассемблера должна быть представлена двоичным числом.Для простоты предположим, что каждой инструкции на языке ассемблера присвоен уникальный номер, например:
- LOADA — 1
- LOADB — 2
- CONB — 3
- SAVEB — 4
- SAVEC mem — 5
- ADD — 6
- SUB — 7
- MUL — 8
- DIV — 9
- COM — 10
- Адрес JUMP — 11
- Адрес JEQ — 12
- Адрес JNEQ — 13
- Адрес JG — 14
- Адрес JGE — 15
- Адрес JL — 16
- Адрес JLE — 17
- STOP — 18
Эти числа известны как коды операций .В ПЗУ наша маленькая программа будет выглядеть так:
// Предположим, что a находится по адресу 128 // Предположим, что F находится по адресу 129Addr opcode / value0 3 // CONB 11 12 4 // SAVEB 1283 1284 3 // CONB 15 16 4 // SAVEB 1297 1298 1 // LOADA 1289 12810 3 // CONB 511 512 10 // COM13 14 // JG 1714 3115 1 // LOADA 12916 12917 2 // LOADB 12818 12819 8 // MUL20 5 // SAVEC 12921 12922 1 // LOADA 12823 12824 3 // CONB 125 126 6 // ADD27 5 // SAVEC 12828 12829 11 // JUMP 430831 18 // STOP
Вы можете видеть, что семь строк кода C стали 18 строками ассемблера, а это стало 32 байта в ПЗУ.
Расшифровка
Декодер команд должен превратить каждый из кодов операции в набор сигналов, которые управляют различными компонентами внутри микропроцессора. Возьмем в качестве примера инструкцию ADD и посмотрим, что ей нужно делать:
- Во время первого тактового цикла нам нужно фактически загрузить инструкцию. Следовательно, декодер команд должен: активировать буфер с тремя состояниями для программного счетчика; активировать строку RD; активировать буфер с тремя состояниями ввода данных; защелкнуть команду в регистре команд.
- Во время второго тактового цикла команда ADD декодируется. .Для этого нужно очень немногое: настроить операцию ALU на добавление фиксации вывода ALU в регистр C
- Во время третьего тактового цикла счетчик программы увеличивается (теоретически это может перекрываться во втором тактовом цикле. ).
Каждая инструкция может быть разбита на набор таких последовательных операций, которые управляют компонентами микропроцессора в правильном порядке. Некоторые инструкции, такие как эта инструкция ADD, могут занимать два или три тактовых цикла.Другие могут занять пять или шесть тактов.
.