Чип 8087 обеспечивал быстрые вычисления с плавающей запятой для первого IBM PC и со временем стал частью x86-архитектуры, используемой и сегодня. Одна необычная особенность 8087 — многоуровневое ПЗУ (ROM, Read-Only Memory), где каждая ячейка кодировала два бита (четыре уровня), что давало плотность примерно вдвое выше обычного ПЗУ. Вместо хранения двоичных данных каждая ячейка ПЗУ 8087 хранила одно из четырёх уровневых значений, которое затем декодировалось в два двоичных бита. Поскольку 8087 требовалось большое ПЗУ микрокода(примеч.1), а сам чип уже упирался в пределы по числу транзисторов, которые можно было разместить на кристалле, Intel применил этот специальный приём, чтобы ПЗУ «влезло». В этой статье я объясню, как Intel реализовал это многоуровневое ПЗУ.
Intel представила 8087 в 1980 году, чтобы повысить производительность операций с плавающей запятой на процессорах 8086 и 8088. Поскольку ранние микропроцессоры работали только с целыми числами, арифметика с плавающей запятой была медленной, а трансцендентные операции — такие как тригонометрия или логарифмы — выполнялись ещё хуже. Добавление сопроцессора 8087 ускоряло операции с плавающей запятой до 100 раз. Архитектура 8087 стала частью более поздних процессоров Intel, а инструкции 8087 (хотя сейчас они уже устарели) до сих пор остаются частью современных настольных x86-компьютеров.
Я вскрыл чип 8087 и сделал микрофотографии кристалла, собрав композитное изображение ниже. Подписи показывают основные функциональные блоки на основе моего реверс-инжиниринга. (Чтобы открыть изображение в полном размере, кликните тут). Кристалл 8087 довольно сложный и содержит 40 000 транзисторов.(примеч.2) Внутри 8087 использует 80-битные числа с плавающей запятой: 64-битную дробную часть (её также называют значащей частью или мантиссой), 15-битную экспоненту и бит знака. (Для аналогии с десятичной записью: в числе 6,02×10^23 величина 6,02 — это дробная часть, а 23 — экспонента.) В нижней части кристалла область «обработка дробной части» обозначает схемы, работающие с дробной частью: слева направо это хранилище констант, 64-битный сдвигатель, 64-битный сумматор/вычитатель и стек регистров. Выше расположены схемы обработки экспоненты.

Одна инструкция 8087 выполнялась в несколько шагов — в некоторых случаях их было больше 1000. 8087 использовал микрокод, чтобы задавать низкоуровневые действия на каждом шаге: сдвиги, сложения, чтение из памяти, чтение констант и так далее. Микрокод можно представлять как простую программу, записанную в виде микроинструкций, где каждая микроинструкция формировала управляющие сигналы для разных узлов чипа. На фотографии кристалла выше видно ПЗУ, в котором хранится программа микрокода 8087. Это ПЗУ занимает значительную часть кристалла — поэтому и понадобилось компактное многоуровневое ПЗУ. Слева от ПЗУ находится «движок», исполнявший программу микрокода, — по сути, простой процессор.
8087 работал как сопроцессор совместно с 8086. Когда 8086 встречал специальную инструкцию с плавающей запятой, процессор игнорировал её и позволял 8087 выполнять эту инструкцию параллельно.(примеч. 3) Я не буду подробно объяснять внутреннюю работу 8087, но в общих чертах операции с плавающей запятой реализовывались через целочисленные сложения/вычитания и сдвиги. Чтобы сложить или вычесть два числа с плавающей запятой, 8087 сдвигал их до совпадения двоичных точек (то есть десятичных точек, но в двоичном виде), а затем складывал или вычитал дробную часть. Умножение, деление и квадратный корень выполнялись через повторяющиеся сдвиги и сложения или вычитания. Трансцендентные операции (tan, arctan, log, возведение в степень) использовали алгоритмы CORDIC, которые опираются на сдвиги и сложения специальных констант, обрабатывая по одному биту за раз. 8087 также учитывал множество особых случаев: бесконечности, переполнения, NaN («не число»), денормализованные числа и несколько режимов округления. Всеми этими операциями управлял микрокод, хранящийся в ПЗУ.
Реализация ПЗУ
Чип 8087 состоит из маленького кремниевого кристалла, в котором участки кремния легированы примесями, чтобы придать им нужные полупроводниковые свойства. Сверху на кремнии расположен поликремний (особый тип кремния), из которого сформированы проводники и транзисторы. Наконец, самый верхний металлический слой соединяет элементы схемы между собой. На фотографии ниже слева показан небольшой фрагмент чипа таким, как он выглядит под микроскопом: видна жёлтоватая металлическая разводка. Справа металл удалён кислотой, и стали видны поликремний и кремний. Там, где поликремний пересекает кремний, образуется транзистор. Розовые области — это легированный кремний, а тонкие вертикальные линии — поликремний. Маленькие кружки — это контакты между кремниевым и металлическим слоями, которые соединяют их между собой.

Хотя способов построить ПЗУ много, типичный вариант — это решётка «ячеек», где каждая ячейка хранит один бит. В ячейке может быть транзистор, соответствующий биту 0, либо транзистора может не быть — это будет бит 1. На схеме выше видна сетка ячеек с транзисторами (там, где под поликремнием присутствует кремний) и отсутствующими транзисторами (там, где в кремнии оставлены «пропуски»). Чтобы прочитать данные из ПЗУ, по адресу активируется одна линия выбора столбца, и тем самым выбираются биты, записанные в этом столбце: с каждой строки получается по одному выходному биту. На рисунке видны вертикальные поликремниевые линии выбора столбца и горизонтальные металлические выходы строк. Вертикальные линии легированного кремния подключены к земле.
Схема ниже (соответствующая сегменту ПЗУ 4×4) показывает, как это ПЗУ работает. В каждой ячейке либо есть транзистор (чёрный), либо его нет (серый). Когда активируется поликремниевая линия выбора столбца, транзисторы в этом столбце открываются и «сажают» соответствующие металлические выходы строк на землю. (Для наших целей NMOS-транзистор можно считать ключом: он разомкнут, если на входе (затворе) 0, и замкнут, если на входе 1.) Строковые линии выдают данные, хранящиеся в выбранном столбце.

Сигналы выбора столбцов формируются схемой дешифратора. Поскольку она построена на элементах ИЛИ-НЕ (NOR), сначала объясню, как устроен элемент NOR. На схеме ниже показан четырёхвходовый NOR, собранный из четырёх транзисторов и подтягивающего резистора (на самом деле это специальный транзистор). Слева все входы равны 0, поэтому все транзисторы закрыты, и подтягивающий резистор тянет выход вверх. Справа один из входов равен 1, транзистор открывается. Транзистор подключён к земле, поэтому он тянет выход вниз. Итого: если хотя бы один вход высокий, выход низкий — значит, схема реализует элемент NOR.

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

На фотографии ниже показан небольшой фрагмент дешифратора ПЗУ со всеми восемью входами элементов NOR. Двоичные адреса можно прочитать, внимательно изучая подключения адресных линий. Обратите внимание на двоичный рисунок: подключения a1 чередуются в каждом столбце, подключения a2 — через каждые два столбца, a3 — через каждые четыре столбца и так далее. Подключение a0 фиксировано, потому что эта часть дешифратора выбирает нечётные столбцы; аналогичная схема выше ПЗУ выбирает чётные адреса. (Такое разделение понадобилось, чтобы дешифратор поместился на кристалле, поскольку каждый столбец дешифратора вдвое шире ячейки ПЗУ.)

Последний компонент ПЗУ — набор мультиплексоров, который сводит 64 выходные линии строк к 8 выходным линиям.(примеч.4) Каждый мультиплексор 8-к-1 выбирает один из восьми входов в зависимости от адреса. На схеме ниже показан один из таких строковых мультиплексоров в 8087. Он построен на восьми больших проходных транзисторах, каждый из которых подключён к одной из строк. Все транзисторы сходятся на выход, так что когда выбранный транзистор открыт, он передаёт свой входной сигнал на выход. Транзисторы мультиплексора намного, намного больше транзисторов в самом ПЗУ — это сделано, чтобы уменьшить искажения сигнала ПЗУ. Дешифратор (похожий на обсуждавшийся выше, но меньшего размера) формирует восемь управляющих линий мультиплексора из трёх адресных линий.

Итого: ПЗУ хранит биты в виде решётки. Восемь адресных бит выбирают столбец в этой решётке. Затем три адресных бита выбирают нужные восемь выходов из строковых линий.
Многоуровневое ПЗУ
До этого мы разобрали типичное ПЗУ, где в каждой ячейке хранится один бит. Так как же 8087 умудрялся хранить два бита в одной ячейке? Если присмотреться, в ПЗУ микрокода 8087 используются транзисторы четырёх разных размеров (если считать «транзистора нет» отдельным вариантом).( примеч.6) При четырёх возможных вариантах ячейка может кодировать два бита, то есть плотность хранения примерно удваивается.(примеч.7) В этом разделе я объясню, как четыре размера транзисторов дают четыре разных значения тока и как аналоговая и цифровая части чипа преобразуют эти токи в два бита.

Размер транзистора определяет ток, проходящий через него.(примеч.8) Важный геометрический параметр здесь — меняющаяся ширина кремния (розовым), который пересекается поликремнием (вертикальные линии), из-за чего получаются транзисторы с разной шириной затвора. Поскольку ширина затвора задаёт ток через транзистор, четыре размера транзисторов дают четыре разных значения тока: самый большой транзистор пропускает максимальный ток, а если транзистора нет вовсе, ток не течёт вообще.
Ток из ПЗУ преобразуется в биты в несколько этапов. Сначала схема подтяжки (pull-up) преобразует ток в напряжение. Затем три компаратора сравнивают это напряжение с опорными напряжениями и формируют цифровые сигналы, показывающие, ниже или выше опоры находится напряжение ПЗУ. Наконец, логические элементы преобразуют выходы компараторов в два выходных бита. Такая схема повторяется восемь раз, в сумме формируя 16 выходных бит.

Схема выше выполняет все эти шаги преобразования. Внизу один из транзисторов ПЗУ выбирается линией выбора столбца и мультиплексором (о нём говорилось ранее), в результате получается один из четырёх токов. Затем подтягивающий резистор(примеч.12) преобразует ток транзистора в напряжение — величина напряжения зависит от размера выбранного транзистора. Компараторы сравнивают это напряжение с тремя опорными и выдают 1, если напряжение ПЗУ выше соответствующего опорного. Компараторы и опорные напряжения нужно было проектировать очень тщательно, потому что напряжения ПЗУ могли отличаться всего на 200 мВ.
Опорные напряжения расположены посередине между ожидаемыми уровнями напряжения ПЗУ, что даёт некоторый запас на колебания. Самое низкое напряжение ПЗУ ниже всех опорных — поэтому все компараторы выдадут 0. Второе напряжение ПЗУ выше Reference 0, поэтому нижний компаратор выдаст 1. Для третьего напряжения ПЗУ нижние два компаратора выдадут 1, а для самого высокого напряжения ПЗУ все компараторы выдадут 1. (Правка: я перепутал уровни напряжений на компараторах: Ref 0 — самый высокий, а Ref 2 — самый низкий, так что поведение получается обратным.) Таким образом, три компаратора дают четыре разных шаблона выходов в зависимости от транзистора ПЗУ. Затем логические элементы преобразуют выходы компараторов в два выходных бита.(примеч.10)
Конструкция компаратора интересна тем, что это мост между аналоговым и цифровым мирами: он выдаёт 1 или 0 в зависимости от того, выше или ниже напряжение ПЗУ относительно опорного напряжения. Каждый компаратор содержит дифференциальный усилитель, который усиливает разность между напряжением ПЗУ и опорным напряжением. Выход дифференциального усилителя подаётся на защёлку, которая стабилизирует сигнал и приводит его к логическим уровням. Дифференциальный усилитель (показан ниже) — это стандартная аналоговая схема. Источник тока (обозначен символом внизу) обеспечивает постоянный ток. Если у одного из транзисторов входное напряжение выше, чем у другого, через него проходит большая часть тока. Падение напряжения на резисторах приводит к тому, что соответствующий выход опускается ниже, а другой выход поднимается выше.

На фотографии ниже показан один из компараторов на чипе: сверху расположен металлический слой, а под ним — транзисторы. Я остановлюсь только на ключевых моментах этой сложной схемы; подробности см. в примечании 12. Сигнал от ПЗУ и мультиплексора входит слева. Подтягивающая цепь(примеч.12) преобразует ток в напряжение. Два крупных транзистора дифференциального усилителя сравнивают напряжение ПЗУ с опорным напряжением (оно подаётся сверху). Выходы дифференциального усилителя идут на схему защёлки (она «размазана» по фотографии); выход защёлки находится внизу справа. Источник тока дифференциального усилителя и подтягивающие элементы (нагрузки) реализованы на транзисторах обеднённого типа. Каждый выходной тракт использует три компаратора, так что всего их получается 24.

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

Собрав всё вместе, на фотографии ниже показано расположение компонентов ПЗУ микрокода на кристалле.(примеч.12) Основную часть схемы ПЗУ составляют транзисторы, в которых хранятся данные. Схемы дешифраторов столбцов находятся сверху и снизу. (Половина дешифраторов выбора столбцов размещена сверху, половина — снизу, чтобы они лучше помещались.) Выходная часть находится справа. Восемь мультиплексоров сводят 64 строковые линии к восьми выходным линиям. Эти восемь сигналов затем подаются на компараторы, которые формируют 16 выходных бит ПЗУ справа. Опорная схема над компараторами генерирует три опорных напряжения. Внизу справа небольшой строковый дешифратор управляет мультиплексорами.

Хотелось бы надеяться, что многоуровневое ПЗУ окажется вдвое меньше обычного, но на практике оно не настолько эффективно: мешает дополнительная обвязка компараторов, а сами транзисторы пришлось сделать чуть крупнее, чтобы реализовать несколько размеров. Тем не менее многоуровневое ПЗУ сэкономило примерно 40% площади, которую заняло бы обычное ПЗУ.
Теперь, когда я определил структуру ПЗУ, я мог бы просто (хотя и довольно занудно) считать его содержимое, рассматривая под микроскопом размер каждого транзистора. Но без знания набора микроинструкций микрокода содержимое ПЗУ бесполезно.
Выводы
В сопроцессоре 8087 для вычислений с плавающей запятой использовалась любопытная структура «два бита на транзистор», чтобы уместить микрокод на кристалле. Intel повторно применил многоуровневое ПЗУ в 1981 году в обречённой системе iAPX 432.(примеч.11) Насколько я могу судить, интерес к ПЗУ с многоуровневыми ячейками достиг пика в 1980-х, а затем сошёл на нет — вероятно потому, что закон Мура позволял проще наращивать объём ПЗУ, уменьшая стандартную ячейку, чем проектировать нестандартные ПЗУ, требующие специальных аналоговых схем с жёсткими допусками.(примеч.14)
Удивительно, но сама идея многоуровневых ячеек недавно вернулась — на этот раз во флеш-память. Во многих флеш-микросхемах в одной ячейке хранятся два и более бита.(примеч.13) Более того, флеш-память дошла до впечатляющих 4 бит на ячейку (что требует 16 разных уровней напряжения): потребительские продукты на памяти QLC (quad-level cell) были анонсированы недавно. Таким образом, малоизвестная технология из 1980-х может внезапно появиться снова спустя десятилетия.
Примечания и источники (осторожно, много текста)
1. В 8087 — 1648 слов микрокода (если я правильно посчитал), по 16 бит в каждом слове, всего 26 368 бит. Размер ПЗУ не обязан был быть степенью двойки, поскольку Intel могла изготовить его ровно того объёма, который требовался.
2. Источники расходятся в оценке числа транзисторов в 8087: Intel заявляет 40 000 транзисторов, тогда как Wikipedia — 45 000. Разница может быть связана с разными методами подсчёта. В частности, поскольку число транзисторов в ПЗУ, PLA (программируемой логической матрице) и подобных структурах зависит от записанных в них данных, источники часто считают «потенциальные» транзисторы, а не фактическое число физически присутствующих транзисторов. Другие расхождения могут возникать из-за того, учитывают ли подтягивающие транзисторы и считают ли драйверы повышенного тока как несколько транзисторов, включённых параллельно, или как один большой транзистор.
3. Взаимодействие между процессором 8086 и сопроцессором 8087 для вычислений с плавающей запятой устроено не так уж просто; я расскажу о нескольких ключевых моментах. В упрощённом виде всё выглядит так: 8087 «наблюдает» поток инструкций 8086 и выполняет те из них, которые относятся к 8087. Сложность в том, что у 8086 есть буфер предварительной выборки инструкций, поэтому инструкция, которая сейчас выбирается, не совпадает с той, которая исполняется. Поэтому 8087 дублирует буфер предварительной выборки 8086 (или меньший буфер предварительной выборки у 8088), чтобы понимать, что именно делает 8086. Ещё одна сложность — это сложные режимы адресации 8086, которые используют регистры внутри 8086. 8087 не может сам выполнять такие режимы адресации, потому что у него нет доступа к регистрам 8086. Вместо этого, когда 8086 встречает инструкцию 8087, он делает чтение из памяти по вычисленному адресу и игнорирует результат. Одновременно 8087 считывает адрес с шины, чтобы при необходимости использовать этот адрес. Если 8087 в системе отсутствует, можно было бы ожидать исключение, но этого не происходит. Вместо этого в системе без 8087 линкер переписывает инструкции 8087, заменяя их вызовами подпрограмм из библиотеки эмуляции.
4. Причина, по которой в ПЗУ обычно ставят мультиплексоры на выходах строк, в следующем: неэффективно делать ПЗУ с большим числом столбцов и лишь несколькими выходными битами — в таком случае схема дешифратора окажется больше, чем «данные» самого ПЗУ. Решение — «переформатировать» ПЗУ так, чтобы хранить те же самые биты, но с большим числом строк и меньшим числом столбцов. Например, ПЗУ можно сделать в 8 раз «выше» (по строкам) и в 8 раз «уже» (по столбцам), и тогда дешифратор получится в 8 раз меньше.
Кроме того, длинное и узкое ПЗУ (например, 1K×16) неудобно разводить на кристалле, потому что оно не укладывается в простой прямоугольный блок. Однако можно использовать «серпантинную» раскладку. Например, ранние памяти Intel были сдвиговыми регистрами; микросхема 1405 хранила 512 бит в одном длинном сдвиговом регистре. Чтобы уместить его на кристалле, регистр «змейкой» изгибался туда-сюда примерно 20 раз.
5. Некоторые компьютеры IBM использовали необычный способ хранения микрокода: на лавсановых (Mylar) карточках пробивали отверстия (как в обычных перфокартах), а компьютер считывал эти отверстия ёмкостным способом (ссылка). В некоторых компьютерах, например Xerox Alto, часть микрокода хранилась в ОЗУ. Это позволяло программам изменять микрокод, создавая новый набор инструкций под свои задачи. Во многих современных процессорах микрокод перезаписываемый, поэтому с помощью патчей можно исправлять ошибки в микрокоде.
6. Я не заметил четыре размера транзисторов в ПЗУ микрокода, пока в комментарии на Hacker News не упомянули, что в 8087 использовалась технология «два бита на транзистор». Я отнёсся к этому скептически, но, присмотревшись к кристаллу внимательнее, понял, что комментарий был верным.
7. В 1980-х применяли и другие подходы к хранению нескольких бит в одной ячейке. Один из самых распространённых использовали Mostek и другие компании: транзисторы в ПЗУ легировали так, чтобы у них были разные пороговые напряжения. Используя четыре разных пороговых напряжения, в одной ячейке можно было хранить два бита. По сравнению с геометрическим подходом Intel, «пороговый» подход был плотнее (поскольку все транзисторы можно было делать насколько можно маленького размера), но требовал большего числа масок и технологических шагов, чтобы получить несколько уровней имплантации. В этом подходе применялась новая на тот момент технология — ионная имплантация — чтобы точно подбирать уровни легирования каждого транзистора.
Самое заметное влияние ионной имплантации на интегральные схемы было связано с созданием обеднённых транзисторов (depletion-транзисторов, то есть транзисторов с отрицательным пороговым напряжением), которые гораздо лучше работали в качестве подтягивающих элементов в логических элементах. Ионную имплантацию также применяли в микропроцессоре Z-80, чтобы создать своего рода «транзисторные ловушки»: схемы, которые под микроскопом выглядели как обычные транзисторы, но получали такие имплантационные добавки, что становились неработоспособными. Это служило защитой от копирования: производитель, который попытался бы выпускать клоны Z-80, просто «срисовав» кристалл под микроскопом, в итоге получил бы чип, который ломается сразу несколькими способами — причём часть отказов была бы очень трудноуловимой.
8. Ток через транзистор пропорционален отношению ширины затвора к его длине. (Длина — это расстояние между истоком и стоком.) В ПЗУ транзисторы (и все эталонные транзисторы, кроме самого маленького) сохраняют длину постоянной и меняют ширину, поэтому уменьшение ширины снижает ток. Формулы для МОП-транзисторов см. в Википедии.
9. Затвор самого маленького эталонного транзистора делают не уже, а длиннее — из-за свойств МОП-транзисторов. Проблема в том, что эталонные транзисторы должны по размерам «лежать между» транзисторами ПЗУ. В частности, для Reference 0 нужен транзистор меньше самого маленького транзистора ПЗУ. Но самый маленький транзистор ПЗУ уже сделан настолько маленьким, насколько позволяют технологии производства. Чтобы решить это, обратите внимание: поликремний, пересекающий средний эталонный транзистор, заметно толще по горизонтали. Поскольку характеристики МОП-транзистора определяются отношением ширины канала (затвора) к длине канала (W/L), «раздуть» поликремний — по эффекту почти то же самое, что «ужать» кремний, если нужно заставить транзистор вести себя как более маленький (то есть пропускать меньший ток).
10. Логика ПЗУ декодирует размер транзистора в биты так: нет транзистора = 00, маленький транзистор = 01, средний транзистор = 11, большой транзистор = 10. Такой порядок бит экономит несколько логических элементов в схеме декодирования; поскольку соответствие «транзистор → биты» произвольно, то неважно, что последовательность получается «не по порядку». (Подробности см. у Старка в «Two Bits Per Cell ROM».)
11. Интерфейсный процессор Intel iAPX 43203 (1981) использовал многоуровневое ПЗУ, очень похожее на то, что применено в кристалле 8087. Подробности см. в статье «The interface processor for the Intel VLSI 432 32 bit computer», J. Bayliss и др., IEEE Journal of Solid-State Circuits, т. SC-16, стр. 522–530, октябрь 1981.
Интерфейсный процессор 43203 обеспечивал поддержку ввода-вывода для процессора iAPX 432. Intel начала проект iAPX 432 в 1975 году, чтобы создать «микромэйнфрейм» — революционный для 1980-х процессор. Когда проект iAPX 432 столкнулся с задержками, Intel выпустила процессор 8086 как временную меру, представив его в 1978 году. Хотя Intel 8086 стал огромным успехом, дав старт настольному ПК и нынешней архитектуре x86, проект iAPX 432 в итоге оказался провальным и был закрыт в 1986 году.
12. Схема ниже (из статьи «Multiple-Valued ROM Output Circuits») показывает детали узла считывания ПЗУ. В концептуальном виде ПЗУ использует подтягивающий резистор, чтобы преобразовать ток транзистора в напряжение. На практике роль подтяжки выполняет трёхтранзисторная схема (T3, T4, T5). Транзисторы T4 и T5 по сути образуют инвертор, который через T3 даёт отрицательную обратную связь, делая схему менее чувствительной к возмущениям (например, к технологическим разбросам). Компаратор состоит из простого дифференциального усилителя (жёлтый), где T6 выступает источником тока. Выход дифференциального усилителя защёлка (зелёная) преобразует в устойчивый сигнал логического уровня.

13. Флеш-память обычно делят на SLC (single level cell — один бит на ячейку), MLC (multi level cell — два бита на ячейку), TLC (triple level cell — три бита на ячейку) и QLC (quad level cell — четыре бита на ячейку). В целом флеш с большим числом бит на ячейку дешевле, но менее надёжна, медленнее и быстрее изнашивается из-за меньших запасов по уровню сигнала.
14. Журнал Electronics опубликовал короткую заметку «Four-State Cell Doubles ROM Bit Capacity» (стр. 39, 9 октября 1980), где описывалась техника Intel, но статья настолько расплывчата, что скорее вводит в заблуждение. Intel опубликовала подробную статью «Two bits per cell ROM» на COMPCON (стр. 209–212, февраль 1981). Внешняя группа попыталась восстановить более детальные характеристики схем Intel методом обратного проектирования в работе «Multiple-valued ROM output circuits» (Proceedings 14th International Symposium on Multivalue Logic, 1984). Ещё две публикации, посвящённые многозначной памяти: A Survey of Multivalued Memories (IEEE Transactions on Computers, февраль 1986, стр. 99–106) и A review of multiple-valued memory technology (IEEE Symposium on Multiple-Valued Logic, 1998).
Если после этой истории про 8087 хочется глубже понимать, как софт выглядит «изнутри» — на уровне бинарников и реального исполнения, — курс Reverse engineering логично продолжит эту траекторию. В программе: практика распаковки, разбор PE (импорт/экспорт/релокации) и анализ реальных семейств вредоносного ПО. В финале вас будет ждать проектная работа, где можно применить инструменты на своей задаче. Пройдите вступительный тест, чтобы узнать, подойдет ли вам программа курса.
Для знакомства с форматом обучения и экспертами приходите на бесплатные демо-уроки:
29 января 20:00. «Как разыменовать NULL-указатель, если очень хочется». Записаться
5 февраля 20:00. «Уязвимость buffer overflow в ядре Windows». Записаться
19 февраля 20:00. «Способы обмена данными между приложением и драйвером». Записаться