Новаторский Intel 386 (1985 год) стал первым 32-битным процессором линейки x86. У него есть множество внутренних регистров: регистры общего назначения, индексные регистры, селекторы сегментов и более специализированные регистры. В этом посте мы изучим кремниевый кристалл 386 и объясним, как реализованы некоторые из этих регистров на уровне транзисторов. Изученные мной регистры реализованы как статическое ОЗУ, где каждый бит хранится в стандартной восьмитранзисторной цепи, называемой «8T». Исследование этой цепи демонстрирует интересные техники размещения, использованные Intel для «сжатия» двух ячеек с целью минимизации необходимого им пространства.
На схеме ниже показана внутренняя структура 386. Я пометил соответствующие регистры тремя красными прямоугольниками. Два набора регистров находятся в кэше дескриптора сегментов и предположительно хранят элементы кэша, а один набор находится внизу от шины данных. Некоторые из регистров снизу имеют ширину 32 бита, а другие вполовину меньше и содержат 16 битов. Есть другие регистры с другими цепями, но в посте я рассматривать их не буду.
Основные функциональные блоки 386. Это изображение я создал на основе фото кристалла Антуана Берковичи
▍ Ячейки статических ОЗУ 6T и 8T
Для начала я объясню, как статические ячейки 6T и 8T хранят бит. Основная идея ячейки из статического ОЗУ заключается в соединении двух инверторов в контур. Эта цепь будет стабильной, с одним включённым и одним выключенным инверторами, и каждый инвертор поддерживает другой. В зависимости от того, какой инвертор включён, цепь хранит 0 или 1.
Два инвертора в контуре могут хранить 0 или 1
Для записи нового значения в цепь на неё подаются два сигнала, заставляя инверторы принять нужные новые значения. Один инвертор получает новое значение бита, а другой получает противоположное значение бита. Это похоже на «брутфорсный» способ обновления бита, но он работает. Хитрость в том, что инверторы в ячейке малы и слабы, а входные сигналы имеют более высокий ток и способны пересилить инверторы[1].
Шины записи данных (называемые разрядными шинами, bitline) подключаются к инверторам через проходные транзисторы[2]. Когда проходные транзисторы включены, сигналы на шинах записи могут проходить к инверторам. Но когда проходные транзисторы выключены, инверторы изолированы от шин записи.
Таким образом, сигнал управления записью позволяет записывать в инверторы новые значения. (Этот сигнал называется шиной слов (wordline), потому что он управляет доступом к слову данных памяти.) Так как каждый инвертор состоит из двух транзисторов[7], показанная ниже схема состоит из шести транзисторов, образуя ячейку хранения 6T.
При добавлении проходного транзистора появляется возможность записи в ячейку
В ячейке 6T используются одни и те же разрядные шины для чтения и записи. Добавив два транзистора, мы получим цепь 8T, имеющую преимущество: можно записывать в один регистр и считывать из другого одновременно. (То есть файл регистра двухпортовый.) В показанной ниже ячейке 8T два дополнительных транзистора (G и H) используются для чтения. Транзистор G буферизирует значение ячейки; он включается, когда на выходе инвертора высокий сигнал, подтягивая разрядную шину вывода чтения вниз[3]. Транзистор H — это проходной транзистор, блокирующий сигнал, пока в этом регистре не выполняется чтение; он контролируется шиной слов.
Схема ячейки памяти. Каждый транзистор помечен буквой
Для формирования регистров (или памяти) из этих ячеек создаётся сетка. Каждая строка соответствует регистру, а каждый столбец — позиции бита. Горизонтальные линии — это шины слов, выбирающие, доступ к какому слову нужно выполнить, а вертикальные линии — разрядные шины, передающие биты в регистры и из них. Для записи вертикальные разрядные шины предоставляют 32 бита (вместе с их обратным кодом). Для чтения вертикальные разрядные шины получают 32 бита от регистра. Шина слов активируется для чтения или записи выбранного регистра.
Ячейки статической памяти (8T), упорядоченные в сетку
▍ Кремниевые цепи в 386
Прежде чем показывать структуру цепи на кристалле, мне нужно немного рассказать о технологиях, использованных для производства 386. Процессор 386 создавался на технологии CMOS, на основе работающих вместе транзисторов NMOS и PMOS; это стало прогрессом по сравнению с предыдущими чипами x86, построенными на транзисторах NMOS. Intel называла эту CMOS-технологию с техпроцессом 1,5 микрометра CHMOS-III (complementary high-performance metal-oxide-silicon). Предыдущие чипы Intel имели один слой металла, а CHMOS-III позволяла использовать два слоя металла, что сильно упрощало трассировку.
Так как в CMOS использовались и NMOS, и PMOS, производство было более сложным.
В интегральной цепи MOS транзистор формируется там, где поликремниевый проводник пересекается с активным кремнием, создавая затвор транзистора. Транзистор PMOS производится напрямую на кремниевой подложке (n-типа). Однако для транзистора NMOS, наоборот, требовалась подложка p-типа. Она создавалась образованием кармана p-типа — области кремния p-типа, содержащего транзисторы NMOS. Каждый карман p-типа должен быть подсоединён к заземлению; это реализуется подсоединением заземления к специально легированным областям кармана p-типа, называемым well tap.
На схеме ниже показано поперечное сечение двух транзисторов, на котором видны слои чипа. Существует четыре важных слоя: кремний (некоторые области которого легированы для образования активного кремния), поликремний для проводников и транзисторов и два слоя металла. Внизу находится кремний p-типа или n-типа; обратите внимание на карман p-типа слева для транзистора NMOS. Далее идёт слой поликремния. Наверху находятся два слоя металла, обозначенные M1 и M2. Концептуально, чип изготавливается из плоских слоёв, однако слои имеют трёхмерную структуру, на которую влияют лежащие ниже слои. Слои разделены диоксидом кремния («ox») или оксинитридом кремния[4]; оксинитрид под M2 существенно осложнил мою работу.
Поперечное сечение цепи, образованной процессом CHMOS-III. Изображение взято из A double layer metal CHMOS III technology
На изображении ниже показано, как цепь выглядит на кристалле[5]; я убрал слои металла, чтобы показать образующие транзисторы кремний и поликремний. (Как будет рассказано ниже, на этом изображении две статические ячейки, хранящие два бита.) Розоватые и тёмные области — это активный кремний, легированный, чтобы участвовать в цепях, а «фоновый» кремний можно игнорировать. Зелёные линии — это поликремниевые линии поверх кремния. Самый важный элемент здесь — это транзисторы: затвор транзистора образуется, когда поликремний пересекается с кремнием, образуя исток и сток по обе стороны. В верхней части изображения находятся транзисторы PMOS, а в нижней есть карман p-типа, содержащий транзисторы NMOS. (Сам карман не видно.) Всего на изображении видно четыре транзистора PMOS и двенадцать транзисторов NMOS. Внизу элементы well tap соединяют карман с заземлением. Хотя слои металла сняты, контакты между нижним слоем металла (M1) и кремнием или поликремнием заметны в виде едва заметных кругов.
Сильно отредактированный снимок кристалла
▍ Структура регистров в 386
Далее я расскажу о структуре этих ячеек в 386. Для повышения плотности цепей две ячейки размещены бок о бок с зеркальным расположением. Благодаря этому в каждой строке есть два перемежающихся регистра[6]. На схеме ниже показано расположение парных ячеек, соответствующее представленному выше снимку кристалла. Транзисторы A и B образуют первый инвертор[7], а транзисторы C и D — второй инвертор. Проходные транзисторы E и F позволяют разрядным шинам выполнять запись в ячейку. Для чтения транзистор G усиливает сигнал, а транзистор H соединяет выбранный бит с выводом.
Схема двух статических ячеек в 386; приблизительно соответствует физической структуре
Левая и правая стороны почти зеркальны, у каждой половины есть свои управляющие шины чтения и записи. Так как управляющие шины для левой и правой сторон находятся в разных позициях, стороны имеют некоторые различия в структуре; в частности выделяющуюся линию справа. Отзеркаливание ячеек повышает плотность, так как ячейки могут иметь общие разрядные шины.
На схеме ниже показаны различные компоненты кристалла, соответствующие схеме выше. Я нарисовал синим соединения нижнего слоя металла M1, но не отметил соединения M2 (горизонтальные управляющие шины, питание и заземление). «Read crossover» обозначает соединение вывода чтения слева с разрядной шиной (bitline) справа. Чёрными кругами обозначены переходные отверстия между M1 и M2, зелёными кругами обозначены контакты между кремнием и M1, а красноватые круги — это контакты между поликремнием и M1.
Структура двух статических ячеек. Слой металла M1 обозначен синим; горизонтальные шины M2 не показаны
Ещё одна сложность заключалась в том, что перемежающиеся регистры (то есть строки) отзеркалены вертикально, как показано ниже. Это позволяло горизонтальной шине питания питать две строки, то же самое относится и к горизонтальной шине заземления. Это вдвое уменьшает количество необходимых шин питания/заземления, делая структуру более эффективной.
Несколько ячеек памяти
Наличие двух слоёв металла сильно усложняет реверс-инжиниринг цепей. На фото ниже (слева) показана одна из ячеек статического ОЗУ такой, какой она видна под микроскопом. Хотя на фотографии видна структура слоёв металла, в ней есть много неоднозначностей. Сложно различить два слоя металла. Более того, металл полностью скрывает слой поликремния, не говоря уже о находящемся под ним кремнии. Большие чёрные круги — это переходные отверстия между двумя слоями металла. Слабо видимые круги меньшего размера — это контакты между слоем металла и находящимся ниже слоем кремния или поликремния.
Отдельная ячейка в том виде, как она выглядит на кристалле; диаграммы верхнего (M2) и нижнего (M1) слоёв металла
Приложив определённые усилия, я разобрался со слоями металла, которые я показал справа: M2 (наверху) и M1 (внизу). Сравнив левое и правые изображения, можно частично увидеть структуру слоёв металла. Чёрными кругами я обозначил переходные отверстия между слоями, зелёными — контакты между M1 и кремнием, розовыми — контакты между M1 и поликремнием. Стоит отметить, что оба слоя металла упакованы максимально плотно. Структура этой цепи сильно оптимизирована для минимизации площади. Интересно отметить, что уменьшение размера транзисторов не помогло бы уменьшить размер цепи, потому что он ограничен плотностью металла. Это показывает, что процесс производства должен находить баланс между размером металлических, поликремниевых и кремниевых элементов, потому что чрезмерная оптимизация одной из частей не поможет в повышении общей плотности чипа.
На фото ниже показана нижняя часть файла регистра. «Выемка» уменьшает вдвое ширину регистров в самом низу: 4 строки половинной ширины соответствуют восьми 16-битным регистрам. Так как у 386 шесть 16-битных сегментных регистров, то подозреваю, что это сегментные регистры и два загадочных регистра.
Нижняя часть файла регистра
Мне не удалось определить, какие регистры в 386 соответствуют оставшимся регистрам на кристалле. В цепи дескриптора сегментов есть две строки ячеек регистров с ещё десятью строками ниже, что соответствует двадцати четырём 32-битным регистрам. Предположительно, это дескрипторы сегментов. В нижней части тракта данных есть десять 32-битных регистров с цепью T8. Видимые программисту регистры 386 состоят из восьми 32-битных регистров общего назначения (EAX и так далее). У 386 есть различные малоизвестные регистры управления, тестирования и сегментации[7]. У 8086 есть несколько регистров для внутреннего пользования, невидимых программисту, то есть, предположительно, у 386 ещё больше невидимых регистров. Пока я не могу даже приблизительно определить их функциональность.
▍ Выводы
Интересно изучать, как реализованы регистры в реальном процессоре. Существует множество описаний цепей статических ячеек 8T, но оказалось, что физическая реализация сложнее, чем теоретическое описание. Intel приложила много усилий к оптимизации этой цепи, добившись создания плотно упакованного блока. Отзеркалив ячейки горизонтально и вертикально, можно ещё больше повысить плотность.
Реверс-инжиниринг небольшой цепи процессора 386 оказался на удивление сложным процессом, поэтому я не планирую заниматься полным реверс-инжинирингом. Основная сложность в том, что тяжело разобраться в двух слоях металла. Более того, при снятии металла я потерял основную часть поликремния. Наконец, сложно рисовать диаграммы с четырьмя слоями, не превращая их в хаос, но, надеюсь, они вам понятны.
▍ Примечания и ссылки
- Обычно цепь возбуждения записи генерирует сильный низкий сигнал на одной из разрядных шин, переключая соответствующий инвертор на высокий выходной сигнал. Как только инвертор переключается, он заставляет другой инвертор перейти в нужное состояние. Для поддержки этого подтягивающие транзисторы в инверторах слабее обычного.
- Проходной транзистор пропускает через себя сигнал или блокирует его. В CMOS это обычно реализуется при помощи передаточного вентиля с параллельными транзисторами NMOS и PMOS. Ячейка использует только транзистор NMOS, что ухудшает пропускание высокого сигнала, но существенно уменьшает её размер — разумный компромисс для ячейки памяти.
- Для чтения разрядная шина обычно предварительно заряжается до высокого сигнала, а затем ячейка подтягивает шину вниз для 0. Это более компактная схема, чем добавление в каждую ячейку цепи для подтягивания шины наверх.
- Проблема заключается в том. что в 386 используется слой изолирующего оксинитрида кремния, а также обычный диоксид кремния. Я смог удалить металл при помощи доведённой до кипения ортофосфорной кислотой, но при этом снялась и основная часть поликремния. Я продолжаю экспериментировать с таймингами; 20 минут кипения — это слишком долго.
- Изображение представляет собой отредактированный коллаж из нескольких ячеек, потому что при снятии слоёв металла поликремний был сильно повреждён. К сожалению, мне не удалось подобрать процесс для снятия по одному слою металла за раз в 386. Поэтому реверс-инжиниринг 386 оказался гораздо сложнее, чем для предыдущих процессоров, например, 8086; мне приходилось изучать слабые следы поликремния и разгадывать, какие соединения требуются для цепей.
- Возможно, вы задаётесь вопросом, зачем размещать две ячейки бок о бок, вместо того, чтобы просто теснее упаковать их. Предположительно, две ячейки размещались в каждом ряду, чтобы согласовать размер каждого бита с остальной схемой тракта данных. Если цепь регистра вдвое меньше ширины цепи АЛУ, то при соединении каждого бита регистра с соответствующим битом АЛУ придётся впустую потратить кучу места.
- CMOS-инвертор составлен из транзистора NMOS (подтягивающего вывод вниз при 1 на вводе) и транзистора PMOS (подтягивающего вывод вверх при 0 на вводе):
CMOS-инвертор - У 386 есть множество задокументированных, но малоизвестных регистров.
В четвёртой главе «Справочного руководства по программированию 386» говорится о различных регистрах, важных только для программистов операционных систем. В том числе о Global Descriptor Table Register (GDTR), Local Descriptor Table Register (LDTR), Interrupt Descriptor Table Register (IDTR) и Task Register (TR). В нём есть четыре управляющих регистра CR0-CR3; CR0 управляет использованием сопроцессора, страничной организацией памяти и некоторыми другими вещами. Шесть отладочных регистров для аппаратных контрольных точек называются DR0-DR3, DR6 и DR7 (что намекает о наличии незадокументированных регистров DR4 и DR5).
Два тестовых регистра для тестирования TLB называются TR6 и TR7 (что тоже намекает о существовании незадокументированных регистров TR0-TR5). Стоит ожидать, что эти регистры расположены рядом с соответствующими функциональными блоками, а не на тракте данных вычислений.
Узнавайте о новых акциях и промокодах первыми из нашего Telegram-канала ?