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

Хотя операции с плавающей запятой на мейнфреймах были обычным делом уже в 1950-х и 1960-х годах, только в 1980-м Intel представила сопроцессор с плавающей запятой 8087 для микрокомпьютеров.

8087 не был первым чипом с поддержкой плавающей запятой. National Semiconductor представила MM57109 Number Cruncher Unit [«перемалыватель цифр»] – так его реально назвали – в 1977-м. Это был, по сути, чип от научного калькулятора на 12 цифр в новом корпусе, работающий с десятичными значениями в двоичном представлении, и требовавший ввода данных в обратной польской записи. Чип работал до абсурдного медленно: к примеру, на вычисление тангенса могло уйти до секунды. AMD представила свой первый чип с поддержкой плавающей запятой, Am9511, в 1978-м. Этот чип поддерживал 32-битные числа с плавающей запятой, и на вычисление тангенса тратил до 1,4 мс. В итоге Intel купила у AMD лицензию на Am9511 и продавала его как 8231. 8087 на 10 МГц, для сравнения, мог вычислить тангенс за 54 мкс, работая с 80-битным числом с плавающей запятой. Вот насколько быстродействие и точность 8087 были выше его предшественников.

Добавление этого чипа к микрокомпьютеру, к примеру, к IBM PC, могло ускорить операции с плавающей запятой в 100 раз. Это было огромным преимуществом для таких приложений, как AutoCAD, электронные таблицы или авиасимуляторы.
У оригинального IBM PC (1981) на материнской плате был пустой разъём для добавления сопроцессора 8087. На фото ниже можно увидеть большой пустой разъём, над микропроцессором 8088. Интересующиеся могут посмотреть на список приложений, поддерживавших 8087.



Минусом чипа была его стоимость в несколько сотен долларов. Я не нашёл оригинальных цен на 8087, однако он реально был дорогим. Сначала Intel продавала 8087 только в испытанной и отлаженной паре с 8088, поскольку у 8087 были проблемы с таймером. К 1982 году Intel понизила стоимость 8087 до $230, что эквивалентно сегодняшним $500. С точки зрения сегодняшнего мира открытых исходников выглядит странно, что клиентам также приходилось платить за поддержку ПО: использование 8087 с языком BASIC стоило дополнительных $150, а библиотека разработчика от Intel для 8087 стоила $1250.

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

Разработчики так прокомментировали советы профессора Кэхэна: «Получилось хуже, чем хотели, но лучше, чем ожидалось». За свою работу с числами с плавающей запятой Кэхэн позднее получил премию имени Тьюринга. Так и появилась архитектура с плавающей запятой 8087. Она стала стандартом IEEE 754, который используется почти во всех современных компьютерах, почему я и считаю 8087 одним из наиболее влиятельных чипов из когда-либо разработанных.


Кристалл Intel 8087 с размеченными основными функциональными блоками. Его размер 5?6 мм. Красным обведён сдвиговый регистр.

Чтобы разобраться в принципах работы 8087, я вскрыл этот чип и сделал фотографии кремниевого кристалла через микроскоп. На нём находится 40 000 транзисторов, и его изготовление реально находилось на пределе возможностей технологий того времени. Для сравнения, в микропроцессоре 8086 было всего 29 000 транзисторов. Сделать такой чип позволили новые технологии, разработанные в Intel. В этой статье я концентрируюсь на высокоскоростном сдвиговом регистре. Сдвиговый регистр занимает значительную часть площади чипа, поэтому для создания 8087 было жизненно необходимо минимизировать его размер.

Число с плавающей запятой состоит из дробной части (также известной, как мантисса), экспоненты и знакового бита. В чипе они реализованы в двоичной системе, но по аналогии с десятичной, у числа 6,02?1023 мантисса будет 6,02, а экспонента – 23. Обрабатывающая мантиссу схема видна внизу фотографии. Слева направо, она состоит из: ROM с константами, сдвигового регистра, сумматоров/вычитателей, стека регистров. Схема обработки экспоненты находится в середине. Над ней – модуль микрокода и ROM управления.

Сдвиговый регистр


Сдвиговый регистр занимается сдвигом двоичных чисел влево или вправо. У этой задачи есть несколько критически важных ролей в операциях с плавающей запятой. При сложении или вычитании двух чисел с плавающей запятой их нужно сдвигать так, чтобы выровнять двоичные разделители. Двоичный разделитель – это как десятичный разделитель, только для двоичных чисел. Трансцендентные инструкции 8087 работают за счёт сложений и сдвигов с использованием алгоритмов CORDIC. Сдвиговый регистр также используется для сборки чисел с плавающей запятой из 16-битных кусочков при чтении из памяти.

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

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

Intel использовала двухступенчатую схему сдвига, которая не разрастается слишком сильно, и при этом обеспечивает достаточно большую скорость работы. Первая ступень сдвигает значение на 0-7 бит, вторая – на 0-7 байт. Вместе они сдвигают значение на любое число битов от 0 до 63.

Побитовый сдвиговый регистр


Начну с описания побитового сдвигового регистра, делающего сдвиг на величину от 0 до 7 битов. На диаграмме ниже обрисована структура побитового сдвигового регистра с пятью входами и выходами. Полноценный сдвиговый регистр поддерживает 68 бит. 8087 использует 64-битную мантиссу и три дополнительных бита для округления, то есть, поддерживает 67 бит. И, если я не ошибся, у него есть ещё один дополнительный бит в значащем разряде, итого получается 68.

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


Структура побитового сдвигового регистра.

Чтобы описать внутреннюю структуру сдвигового регистра, я начну с описания N-МОП транзисторов, использовавшихся в 8087. Транзисторы делают при помощи добавления на кремниевую подложку особых примесей, которые создают участки «диффундированного» кремния с различными электрическими свойствами. Транзистор можно считать переключателем, контролирующим поток электрического тока между двумя участками, истоком и стоком. Активируется транзистор затвором, состоящим из особого типа кремния, поликремния, расположенного отдельным слоем над кремниевой подложкой. Подача напряжения на затвор позволяет току течь между истоком и стоком, а иначе этот путь заблокирован. Соединяются транзисторы металлическим слоем, находящимся сверху, при помощи которого получают сложную интегральную схему.


МОП-структура

На фото ниже показан транзистор из 8087 так, как его видно под микроскопом. Его структура соответствует диаграмме выше, однако форма гораздо сложнее. Исток, сток и затвор выходят за пределы фото, и соединяются с другими транзисторами. Кроме того, проводники в металлическом слое соединяются с кремнием кольцевыми дорожками (металлический слой для этого фото был удалён кислотой).


N-МОП транзистор в чипе 8087, под микроскопом

Если немного уменьшить увеличение, то можно рассмотреть диаграмму ниже, на которой показано, как побитовый сдвиговый регистр реализован на чипе. На этом фото уместилось 48 транзисторов, похожих на тот, чьё фото я привёл выше. Оранжевая и жёлтая диагональные линии соответствуют одному из входов. Оранжевые участки отмечают транзисторы, соединённые через кремний, а жёлтые – соединённые через металлический слой. Металлический слой используется для того, чтобы перепрыгивать через шины выборки из поликремния. Зелёным показана шина выборки из поликремния для сдвига на 3. В центре шина поликремниевого затвора включает транзистор, соединяющий вход с выходной длинной жёлтой линией, и сдвигающей отмеченный вход на три шага. Таким способом данная схема реализует сдвиговый регистр, как он был описан в начале данного раздела. На фото видно 6 из 68 входов, поэтому целиком сдвиговый регистр выглядит гораздо больше.


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

Побайтовый сдвиговый регистр


Побайтовый сдвиговый регистр сдвигает входящие данные на количество шагов, кратное не одному, а восьми битам. По принципу работы он схож с побитовым сдвиговым регистром, только у него каждый вход соединён с каждым восьмым выходом. К примеру, вход 20 соединён с выходами 20, 28, 36 и т.д. В итоге диагональные связи сильно наклонены и находятся близко друг к другу. На диаграмме ниже отмечена шина для сдвига на 4, и отмечены связи входа 0 с выходом 32. В правой части диаграммы нет проводников – любой бит, сдвинутый за пределы входа 0, обнуляется. К примеру, при сдвиге влево на 4 байта младшие биты от 31 и ниже обнуляются.


Структура побайтового сдвигового регистра

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

Чтобы втиснуть проводники как можно ближе друг к другу, в сдвиговом регистре чередуются проводники из диффундированного кремния и проводники из поликремния. На фото ниже проводники из диффундированного кремния розоватые, а из поликремния – желтоватые. 8087 производили по техпроцессу HMOS III от Intel, требовавшего промежутков размером 4 мкм для поликремния и 5 мкм для диффузии – возможно, из-за разрешения фотолитографии. Однако бывает, что расстояние между диффундированным кремнием и поликремниевыми шинами оказывается гораздо меньшим – вероятно потому, что их создавали при помощи отдельных фотошаблонов на отдельных слоях. Поэтому эти чередующиеся шины могут находиться очень близко друг к другу, экономя пространство.


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

Отметьте также, что верхняя часть побайтового сдвигового регистра частично пуста, а внизу он заполнен большим количеством проводников. Расположение проводников не такое аккуратное, как на диаграмме, но разработано для получения максимальной эффективности.


Побитовый сдвиговый регистр и побайтовый сдвиговый регистр чипа 8087

Двунаправленные драйверы


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

Пока что наши побитовый сдвиговый регистр и побайтовый сдвиговый регистр сдвигали биты только в одном направлении. Однако биты требуется сдвигать в обоих направлениях. Одной из ключевых инноваций сдвигового регистра 8087 была двунаправленная схема работы. Для сдвига битов в противоположном направлении данные через сдвиговый регистр можно было передавать в обратном направлении. Это возможно благодаря тому, что сдвиговый регистр состоит из пропускающих транзисторов [pass transistors], а не логических вентилей. Логика на пропускающих транзисторах [PTL] использует транзисторы в качестве коммутаторов, пропускающих или блокирующих сигнал, так, что сигнал может идти в обоих направлениях. У обычных же логических вентилях, таких, как NOR, есть определённые входы и выходы.

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

У схемы драйвера есть несколько тонкостей. Она не отправляет данные напрямую на сдвиговый регистр – биты передаются в два шага. Сначала шины сдвигового регистра предварительно заряжаются до высокого уровня. Затем любой вход 1 бита приводит к тому, что соответствующие шины сдвигового регистра притягиваются вниз. Иначе говоря, шины сдвигового регистра возбуждаются низким уровнем сигнала – низкое напряжение соответствует 1. Поскольку у всех не использующихся входов остаётся высокое напряжение (что соответствует биту 0), нулевые биты сдвигаются в сторону младших автоматически. Думаю, что технология предварительного заряда лучше подходила для N-МОП, поскольку она лучше справлялась с притягиванием сигнала вниз, чем вверх. Такой подход увеличивал быстродействие, особенно учитывая относительно высокую ёмкость таких транзисторов. Защёлка между сдвиговым регистром и шиной мантиссы предотвращает нежелательный цикл, в котором сдвинутые данные пойдут обратно в сдвиговый регистр и снова сдвинутся.

Мультиплексор и декодеры


Последнее, что я опишу – это электроника, управляющая сдвиговым регистром. Количество позиций сдвига контролируют три источника. Во-первых, микрокод может напрямую задавать это число. Во-вторых, число может прийти от счётчика петель – этот случай используется в рамках алгоритмов CORDIC. Наконец, число может прийти от счётчика ведущих нулей – это позволяет нормализовать числа, устраняя ведущие нули через сдвиги. Каждый из источников выдаёт 6-битное число сдвига; каждый из мультиплексоров берёт один бит из нужного источника. Также каждый источник должен сообщить направление сдвига, налево/направо – однако отвечающую за это электронику я пока не нашёл.


Схема мультиплексора/декодера.

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

Каждый декодер, по сути, состоит из восьми NOR-вентилей: семь притягиваются вниз, и только один, на всех входах которого будет низкий сигнал, притянется вверх. Однако реализовано это не в виде простого логического вентиля. Все выходы предварительно имеют высокий сигнал, а потом семь ненужных выходов притягиваются вниз. Такая динамическая логика предварительного заряда используется до сих пор – см. книгу Synchronous Precharge Logic. По той же схеме реализованы и мультиплексоры. Внизу схемы видно, как 16 управляющих шин выходят наружу.

Заключение


8087 – сложный чип со многими функциональными модулями. Однако, если тщательно изучить кристалл, можно разобраться в электронных схемах 8087. В другом посте я описал устройство быстрого сдвига 8087, способное сдвигать биты до 63 позиций за раз. У процессоров Intel x86 не было устройства быстрого сдвига вплоть до 80386 (1985), где появилось 64-битное устройство быстрого сдвига. До того 8086 и его потомки сдвигали по биту за раз, поэтому сдвиг на много позиций проходил куда как медленнее. На этот инновационный программируемый двунаправленный сдвиговый регистр у Intel есть патент.

Сдвиговый регистр стал лишь одной из особенностей 8087, позволявшей ему проводить операции с плавающей запятой гораздо быстрее, чем это мог процессор 8086. 8087 работает с 80 битами за раз, а не с 16. У 8087 регистры были шириной 80 бит, что уменьшало количество запросов к памяти во время вычислений. В 8087 были встроены проверки на NaN, исчезновение значащих разрядов, переполнение, и т.п., благодаря чему можно было избавиться от медленных проверок этого в коде. 8087 ускорял операции умножения и деления. Относительный вклад этих факторов мне неизвестен, однако в целом все они кардинально ускоряли работу с плавающей запятой, бывало, что и до 100 раз.

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


Фото кристалла 8087 с удалённым металлическим слоем. Цвета дают остатки оксидов. Кликабельно.