- PVSM.RU - https://www.pvsm.ru -
Про предмет статьи ходит много домыслов — от «русский Барроуз» до «не имеющий аналогов». Вызвано это в немалой степени отсутствием (доступной) полноценной документации, немногочисленным кругом лиц, имевших с ними дело да и немалым временем, прошедшим с тех пор. «Эльбрус» превратился в один из мифов ушедшей эпохи.
С другой стороны, вычислительный комплекс несомненно существовал и показывал отличные для своего времени результаты. Возможно, благодаря скудости элементной базы, которая принуждала разработчиков к выдумыванию разного рода архитектурных трюков. Многие из этих трюков сейчас выглядят архаично, а некоторые достаточно актуальны.
Так что автор из свойственной ему любознательности попытался разобраться с доступной документацией и составить более — менее цельную картину. Если читателю это интересно — добро пожаловать под кат.
Новое поколение техники возникает не тогда, когда подросло новое поколение инженеров, а на основе качественных изменений в технологии. В том, что касается советских “Эльбрусов”, таким изменением стало появление интегральных схем. Для «Эльбрус-1», это была 133 серия [1] микросхем с логикой ТТЛ [2] (быстродействие 10...15 нс на вентиль). Для «Эльбрус-2» — 100-я серия [3] с логикой ЭСЛ [4] (быстродействие 2 нс на вентиль).
100 серия сделана (серийный выпуск с 1974 г.) на основе MECL 10K от Motorola [5] (с 1971 г.) [6]. 133 серия (с 1969 г.) базировалась на 54 серии от TI [6] (с 1965 г.) [6]. Т.е. какого-то особого отставания в элементной базе на тот момент не было.
Подсистема памяти строилась на базе микросхемы К565РУ3В [7] (NMOP [8]) [3] ёмкостью 16Кбит и организацией 16384х1.
Аппаратура коррекции и контроля позволяет исправлять одиночные и обнаруживать двойные ошибки при считывании информации. Для этого при записи формируются и добавляются к 72-разрядному информационному слову восемь разрядов кода Хемминга. Таким образом, слово, хранящееся в памяти, содержит 80 разрядов, включая: 8 — управляющая информация (тег), 64 — данные, 8 — контрольные разряды кода Хемминга.
Адресная шина имеет разрядность — 24, т.е. размер физической памяти ограничен 16 мега-словами (по 72 бита), 144 Мб данных вместе с тегами.
Если считать вместе с кодами Хэмминга, получим 180 Мб или 90 Кмикросхем. Всё это удалось для максимальной комплектации разместить в 8 шкафах (секциях ОП).
В максимальную комплектацию входит 10 процессоров, при этом каждый процессор соединен с каждой секцией ОП. Длина линий связи выбрана примерно равной 10 м из условия размещения устройств комплекса. Такую длину свет пролетает в вакууме за ~1/30000000 секунды (33 нс). В Э-2 же сигналы передаются от выходного регистра передающей станции до регистра приемника за 80 нс (при рабочем цикле в 44 нс), что очень неплохо.
Каждый шкаф памяти (секция ОП) состоит из четырёх модулей памяти и коммутатора. Модули функционально независимы и могут одновременно обмениваться информацией с разными процессорами. Всего 32 модуля, в каждом по половине мега-слова. При групповом обращении все четыре модуля запускаются одновременно. Это позволяет получить максимальный темп обмена данными с секцией ОП.
Цикл работы модуля составляет 13 тактов, однако последовательные обращения к разным микросхемам одной группы могут обслуживаться каждые семь тактов.
На нижнем уровне, минимальный размер блока — 16К слов соответствует объему микросхемы памяти 16К бит. Блок состоит из 80 микросхем памяти, по одной микросхеме на разряд. Следовательно, модуль памяти состоит из 32 таких минимальных блоков.
Является частью процессора.
Имеет отдельный канал связи с каждой из восьми секций ОП и может обращаться в каждую секцию как с одиночными, так и с групповыми запросами.
При групповом запросе за одно обращение происходит обмен четырьмя словами. Время обращения по записи в память составляет для УООП около восьми тактов, время обращения по считыванию из памяти — около 20 тактов (обращение может быть задержано коммутатором ОП в случае занятости модуля памяти или конфликта по обращению с другим ЦП).
Одновременно в УООП может храниться до трех запросов. УООП имеет внутреннее распараллеливание на два канала, что позволяет выставлять одновременно два запроса на обмен в разные секции ОП. Максимальная частота смены в канале — один запрос за восемь тактов. Таким образом, при групповых обращениях к памяти УООП обеспечивает темп обмена — одно слово за такт [1].
Для оптимизации работы при последовательном обходе адресов используется техника расщепления (interleaving). Часть битов в физическом адресе перемешивается, в результате последовательно идущие слова оказываются в разных единицах вышеописанной иерархии памяти и могут читаться параллельно. Схема перемешивания такова:
При исключении отдельных модулей из конфигурации, операционная система не назначает их адреса. Наличие выключенного модуля делает невозможным расщепление в данной секции.
Математическая память описывается 38-разрядным математическим адресом при условии указания размещения величины с точностью до одного разряда (32-разрядным адресом при указании с точностью до машинного слова).
Основной единицей информации является величина. Величина -логическая единица информации, к которой можно адресоваться с помощью математического адреса. Над величинами же производятся операции при выполнении команд программ.
Величины могут иметь следующие размеры в разрядах (форматы): 1, 4, 8, 16, 32, 64, 128.
Ни одна из величин кроме 128-разрядной не может быть расположена более чем в одном слове.
В одном слове могут находиться величины только одинакового типа и формата за одним исключением: целое и вещественное формата 32 разряда могут быть упакованы в одном слове в любом порядке.
В управляющих разрядах слова хранится информация о типе и формате величин, находящихся в слове.
Математическая память разбита на страницы. Страницы могут быть различных размеров (кратных 16) — от 16 до 1024 слов. Адрес начала страницы имеет младшие 10 (из 38) разрядов нулевыми [2 стр.61].
Блок из 16 слов, расположенный в математической памяти так, что в 38-разрядном адресе первого слова младшие 10 разрядов нулевые, называется строкой.
Сегменты — области непрерывной адресации, выделяемые системой.
Начало любого сегмента в математической памяти совпадает с началом некоторой страницы.
Для размещения сегмента используется страница минимально возможного размера.
Сегменты размером более 1024 слов размещаются в математической памяти на смежных страницах, при этом все страницы, кроме последней, должны иметь максимальный размер.
Начало страницы, а следовательно и сегмента, в физической памяти может размещаться в начале любой физической строки. Страница располагается в смежных ячейках физической памяти.
Поэтому сегмент размером более 1024 слов может присутствовать не полностью в физической памяти (swapping), а его страницы в физической памяти не обязаны идти подряд.
Виртуальная память организована довольно логичным и естественным образом.
Сегменты создаются ядром ОС, что неизбежно, учитывая теговую систему и вопросы защиты памяти.
Все свободные области памяти в ядре объединены в упорядоченный список свободных областей. Упорядочение производится по размеру области. В системе команд имеется специально для этих целей предназначенная команда “ПОИСК ПО СПИСКУ”, которая находит либо область, точно совпадающую по размеру с требуемым, либо минимально превосходящую по размеру требуемый размер. В первом случае найденная область исключается из списка, загружается в математическую память (если это требуется) и в качестве результата процедуры формируется дескриптор этой области. Во втором случае, если размер найденной области превосходит требуемый более чем на 15 слов, из найденной области забирается область требуемого размера, а остаток возвращается в область свободной памяти, где он будет включен в соответствующее место списка свободной памяти. Пользователю выдается дескриптор на область памяти размером, в точности совпадающим с запрашиваемым.
В том случае, если памяти требуемого размера нет, происходит попытка консолидации участков свободной памяти путем перемещения занятых участков меньшего размера, разделяющих соседние свободные области, в имеющиеся свободные области.
Если это не приводит к цели, происходит откачка (свопирование) занятых участков на внешние носители. Это не касается выполняемых сегментов, их можно просто освободить…
Каждая задача имеет свой файл откачки, а каждый сегмент знает свою задачу. Распределение свободной памяти в файле производится по битовой маске[2, стр.143], в которой один разряд соответствует странице. (Для математической памяти размером 2**32, требуется маска в 2**(32-16)=64К на задачу, что не так уж и мало. Кроме того, непонятно как быть со страницами размером меньше максимально возможных 8К.) Таким образом удаётся избежать проблем с поддержанием реестра свободных страниц в сравнении с общим файлом откачки. Ведь каждая задача имеет свою математическую память. Кроме того, высвобождение всей памяти процесса сводится к удалению его файла откачки, работа перекладывается на файловую систему. При относительно небольшом числе задач это отличный подход. К его минусам можно отнести разве что дополнительную нагрузку на файловую систему.
В ядре ОС есть задача, которая в фоновом режиме “подстригает” задачи [2, стр.143], сбрасывая некоторый процент страниц. Данные пассивных задач при этом постепенно оказываются в файлах откачки, активно работающие задачи балансируются.
Разберём теперь преобразование адреса из математического в физический.
Все области памяти задачи (сегменты) объединены списком, голова и хвост которого расположены в дескрипторе задачи. Отметим, что в данной архитектуре не предусмотрены обращения по голому указателю в духе “C”, всегда преобразуется пара (указатель, смещение).
В упомянутом списке сегментов задачи с помощью инструкции “ПОИСК ПО СПИСКУ” находится описатель сегмента, а в нём физический адрес нужной страницы. Если в физической памяти данная страница отсутствует, включается механизм подкачки.
Для ускорения преобразования математического адреса в физический в ЦП для наиболее “активных” страниц предусмотрен ассоциативный массив размером в 64 элемента. Ассоциативным признаком является номер математической страницы, ответ — физический адрес начала страницы, ее размер, а также некоторые служебные признаки. Время поиска в этом ассоциативном массиве — 3 такта, темп обработки — одна заявка в такт.
Кроме того, само слово, к которому происходит обращение, вместе со своим математическим адресом помещается в ассоциативную память слов, которая также имеется у каждого ЦП. Такая память является аналогом современной кэш памяти.
Есть упоминание [2, стр.144] о таблице откачанных страниц (ТОС), предназначенной для размещения информации об откачанных или еще не инициализированных страницах. Голова этой таблицы находится в ОЗУ, область переполнения — во внешней памяти (барабане). Её величина пропорциональна количеству существующих страниц, а не всей математической памяти.
ТОС одна на систему, значит для каждой страницы надо запоминать еще и идентификатор задачи.
Для ускорения работы с ТОС в ядре предусмотрен кэш, причем, как утверждается, весьма эффективный. Но это странно, ведь для эффективного кэширования необходимо понимать логику работы прикладной задачи с памятью, а она разработчикам ОС неизвестна.
Итак:
Как уже говорилось, слово состоит из 64 разрядов данных и 8 управляющих разрядов. Управляющие разряды содержат тег — описание того, что лежит в информационной части слова.
Это может быть:
Мы говорим “безадресная система команд”, подразумеваем — “стековый процессор [11]”.
Рассмотрим простой пример, вычисление выражения x+y*z+u.
При построении дерева разбора [12] компилятором оно выглядит так:
Ассемблерный код (x86) для этого выражения:
mov eax,dword ptr [y] imul eax,dword ptr [z] mov ecx,dword ptr [x] add ecx,eax mov eax,ecx add eax,dword ptr [u] |
Для гипотетической стековой машины псевдокод таков:
push x push y push z multiply add push u add |
Для работы со стеком необходимы операции следующих типов:
Что нам предлагает архитектура Эльбруса?
Отметим, что поскольку стек реализован как циклический буфер из регистров, загрузка нового элемента может вызвать автоматическую выгрузку части стека в память.
Особый интерес представляет загрузка по адресу, при которой:
Исходные числа убираются из стека (с соответствующим смещением указателя), а затем результат помещается в верхушку стека.
Одноместные арифметические операции берут операнд из верхушки стека и заменяют его на результат.
Структурная схема ЦП [1]:
Программный код вычитывается в буфер команд (БК). БК работает как ассоциативный массив, имеет объем в 512 слов, которые поделены на 32 равных сегмента. Подкачка информации в БК из оперативной памяти производится блоками по четыре слова. Темп подкачки определяется необходимым запасом командных слов в буфере команд и автоматически регулируется при изменении темпа декодирования команд.
Схема выборки извлекает очередную команду из БК, дешифрует и передает в УУ для преобразования во внутренний регистровый формат.
Все передачи адресной и числовой информации сопровождаются в ЦП внутренним адресом источника или потребителя информации. Внутренние адреса присвоены буферу команд, стеку операндов (СтОп), БП и некоторым входным регистрам ИУ.
СтОп состоит из 32 регистров и 32-разрядного регистра — битовой маски. Каждый бит в этой маске отвечает за конкретный регистр, 1 — означает занят, 0 — свободен.
При выдаче команды в ИУ формируются внутренние адреса операндов и результата операции. Для операций со стеком, операнды и результат — номера регистров из СтОп.
Для декодирования команды суммирования, например, считается, что номера операндов уже получены ранее, можно назначать любой свободный регистр из СтОп.
После того как команда исполнилась, операнды освобождаются.
Не все команды могут быть исполнены непосредственно после их декодирования, поэтому необходим буфер декодированных, но не исполненных команд. ЦП обладает таким буфером на 32 команды во внутреннем представлении.
Из декодера команды выдаются в последовательности, заданной программой. При этом они последовательно нумеруются и этот номер сопутствует команде всю её жизнь. Этот номер — индекс в упомянутом буфере декодированных команд, когда он доходит до 32, то опять начинает с нуля. Зная текущее значение, можно выстроить все команды в очереди по порядку их декодирования.
Время выполнения команд в ИУ определяется их типом и колеблется от 2 до 20 тактов для операций над операндами однократной точности (32) и до 30 тактов над операндами удвоенной точности (64). ??? Умножение(Ф64) — 4 такта. Деление (Ф64) — 24 такта.
Выполнение операций над вещественными числами формата Ф128 требует трехкратного сложения — сложения младших разрядов, сложения старших разрядов с учетом переноса из младших разрядов, повторного сложения младших разрядов с учетом переноса из старших разрядов. Для этого требуются станции хранения промежуточных результатов.
Исполняться команды начинают по готовности аргументов и доступности нужного исполнительного устройства. Т.к. порядок исполнения не обязательно совпадает с исходным, мы имеем внеочередное исполнение (OoO [13]). А поскольку исполнительных блоков несколько и работают они параллельно, налицо суперскалярность [14]. Правда, сумматор, делитель и умножитель в единственном экземпляре, но могут работать параллельно.
Учитывая, что всего имеется 10 исполнительных устройств, возникает вопрос, а сколько же инструкций за такт может быть исполнено. В [2 стр. 185] упоминается, что в технологическом режиме с последовательным выполнением команд производительность падает в 2-3 раза. В [4] говорится о 2 командах за такт. Связано это, по-видимому, с реализацией СтОп, которая допускает только две записи за такт.
Для демонстрации возможности вполне суперскалярного поведения, разберем выражение “(a * b) + (c / d)”. При этом, переменные “a” & “c” расположены в области локальных переменных процедуры и присутствуют в кэше, а “b” & “d” глобальные и в кэше отсутствуют. Для простоты, все они типа F64.
Ассемблерный код выглядит примерно так:
ВЗ а ДВЗ b ∗ ВЗ c ДВЗ d ⁄ + |
Где ВЗ означает “вызвать значение”, ДВЗ — “длинная ВЗ”, а мнемоники арифметических операций неизвестны.
После декодирования код во внутреннем представлении примерно таков (мнемоники придуманы):
загр a -> R1 ; с захватом R1 в СтОп загр b -> R2 ; с захватом R2 в СтОп ∗ R1 R2 ->R3 ; с захватом R2 в СтОп, R1 & R2 освобождаются по выполнении загр с -> R4 ; с захватом R4 в СтОп загр d -> R5 ; с захватом R5 в СтОп ⁄ R4 R5 ->R6 ; с захватом R6 в СтОп, R4 & R5 освобождаются по выполнении + R3 R6 ->R1 ; с захватом освобожденного было R1 в СтОп, ; R3 & R6 освобождаются по выполнении ; результат в R1 |
Из-за зависимостей между командами исполнение происходит в следующем порядке (2 инструкции за такт, загрузка из кэша — 1 такт, загрузка из памяти 13 тактов, “*”-4 такта, “/” — 24 такта, “+” — 3 такта):
такт | Старт | Исполнилось |
1 | загр a -> R1; загр b -> R2 | |
2 | загр с -> R4; загр d -> R5 | загр a -> R1 |
3 | загр с -> R4 | |
13 | загр b -> R2 | |
14 | ∗ R1 R2 ->R3 | загр с -> R4 |
15 | ⁄ R4 R5 ->R6 | |
17 | ∗ R1 R2 ->R3 | |
38 | ⁄ R4 R5 ->R6 | |
38 | + R3 R6 ->R1 | |
40 | + R3 R6 ->R1 |
Умножение и деление выполняются вполне параллельно. Увы, но арифметические исполнительные устройства не имеют конвейеров, которые планировались только в векторном процессоре [2, стр.150].
Иногда может потребоваться приостановить работу программы с возможностью при необходимости продолжить работу, например, при истечении кванта времени. Для этого требуется восстановление исходного порядка инструкций. При этом
Восстановление состояния регистров потребует специального механизма, например, циклического буфера для лога изменений значений регистров размером 2 * “максимальная длина инструкции в тактах”. В этот лог при завершении инструкции записываются — старое значение регистра из СтОп, новое значение, номер регистра и номер команды. Тогда при необходимости можно открутить назад изменения для отменяемых команд.
Отмена выполнения команд используется также при обработке команд условного перехода. Таким образом осуществляется спекулятивное исполнение кода [15].
Про предсказатель направления ветвления есть упоминание [1], но механизм неясен.
Итак, что мы имеем?
Проблема межпроцессорного взаимодействия связана с наличием у каждого процессора своего СОЗУ (кэш) и, следовательно соответствием данных в ОЗУ и СОЗУ. СОЗУ позволяет значительно снизить частоту обращений в относительно медленную память, но при этом возможна ситуация, когда данные в памяти свежее оных в СОЗУ.
В МВК “Эльбрус” задача может порождать несколько процессов (threads), разделяющих общую математическую память. Участок программы, использующий (считывающий или модифицирующий) общие для нескольких процессов данные, называется критической секцией.
Проблем две — синхронизация и поддержка когерентности кэша [19].
Считается, что работа с общими данными может производиться только в критической секции, то есть между операциями «ЗАКРЫТЬ» и «ОТКРЫТЬ» или операциями «ЖУЖ» и «ОТКСЕМ».
Все данные, записываемые в СОЗУ процессора между этими операциями, помечаются как «общие» и, кроме того, запоминается время их занесения в СОЗУ. Под СОЗУ понимается память глобальных данных объемом 1024 слова [2 стр. 186].
Каждая процедура имеет свое собственное локальное адресное пространство, глобальные данные принадлежат другим процедурам, насколько это позволяет область видимости процедуры. Т.е. для компилятора и для процессора обращения к локальным и глобальным данным неравноценны.
При открытии семафора в него записывается время открытия. При каждом закрытии семафора анализируется записанное в него время и время записи общих данных в СОЗУ. Те общие данные, которые попали в СОЗУ раньше открытия этого семафора, теперь не достоверны, так как могли быть изменены другим ЦП. Те данные, которые попали в СОЗУ после открытия семафора, достоверны, так как они не имеют отношения к данному семафору.
Разберемся на примере. Предположим, речи идет о потоко-безопасном счетчике.
Таким образом, на основании сравнения времени открытия семафора и времени занесения общих данных в СОЗУ, ЦП однозначно решает проблему достоверности данных. При этом не нужно сбрасывать весь глобальный кэш, что нанесло бы удар по производительности.
Чтобы обеспечить всё это, для меж-процессорного взаимодействия введены инструкции:
По всей видимости, так распространяется информация о изменении состояния семафоров.
Также предположительно, таким образом должны распространяться данные, которые заносятся в СОЗУ аппаратно без закрытия каких-либо семафоров. Сюда относятся дескрипторы программных сегментов и таблицы соответствия математических и физических адресов.
Таким же образом можно (было бы) решить проблему доставки изменений в СОЗУ при закрытии семафора до СОЗУ других процессоров.
Параметры вызова функции и локальные переменные лежат в стеке. Контекст вызова также лежит в стеке. В сущности, контекст состоит из двух указателей — на старый контекст (т.е. контексты связаны списком для осуществления выхода из функций) и на инструкцию, с которой произошел вызов. Плюс дополнительная информация, всё это удалось упаковать в два слова.
Но вызов функций в Эльбрусе своеобразен. Он многофазный.
При выходе, если необходимо, функция на месте своего бывшего контекста оставляет возвращаемое значение.
Зачем такие сложности? Почему не вызвать функцию более традиционно, одной инструкцией?
В этом случае параметры функции окажутся перед контекстом и дескриптор области локальных данных, который начинается с этого контекста не сможет их покрыть. Если же сдвинуть начальную область дескриптора назад, на начало области параметров, сломается список стека вызовов, либо придется прописывать в стек псевдо-параметр -длину области параметров. Что фактически та же самая маркировка стека.
Что касается упомянутого дескриптора для доступа к локальным данным, то он не один, их аж 32. И какой из них используется, определяется лексикографическим уровнем функции.
Этот механизм в чем-то похож на уровень привилегий х86 [22]. Имеются 32 базовых регистра дескрипторов, описывающих локальные данные процедур (+параметры) в стеке.
Каждый (как обычный дескриптор области) содержит:
Разные базовые регистры описывают разные контексты стека. Так, регистр №0 содержит дескриптор, описывающий стек из описателей процедур и данных операционных систем, регистры №1 и №2 описывают стеки описателей процедур и внешних имен выполняемой задачи, регистр №3 содержит дескриптор, описывающий стек блока верхнего уровня и так далее.
Таким образом, если некоторая инструкция инструкции содержит закодированное «имя» величины (физически расположенной в стеке), то оно определено только в данном контексте. Доступ к элементу стека осуществляется через лексикографический уровень функции, и порядковый номер слова в области стека, выделенной для данных этой функции (адресная пара).
В процедурах таких языков доступны лишь локальные переменные и параметры вызова. Распределение памяти для каждой вызываемой процедуры производится динамически. При входе в процедуру ей отводится в стеке необходимая область свободной памяти для формальных параметров и локальных переменных, указатель стека (УС) передвигается на новую границу.
Отводимая процедуре область памяти описывается дескриптором, помещенным в один из базовых регистров (пусть N). Обращение к величине в этой области осуществляется с помощью адресной пары (N, И).
Область свободной памяти в стеке ниже новой границы используется для хранения промежуточных результатов.
При выходе из процедуры, отведенная ей область памяти возвращается обратно в область свободной памяти путем восстановления прежнего УС. Таким образом, каждой процедуре отводится ровно столько памяти, сколько потребует динамика ее выполнения, и только тогда, когда это необходимо.
Если из рассматриваемой процедуры Р производится обращение к другой процедуре Q, то для процедуры Q отводится область свободной памяти точно таким же образом, как и для процедуры Р. При этом переменные, описанные в процедуре Р, и ее промежуточные результаты остаются в стеке и могут быть вновь использованы, когда произойдет возврат из процедуры Q.
При выходе из процедуры Q необходимо восстановить содержимое базового регистра с номером N и передать управление на оператор, следующий за оператором вызова процедуры Q. Для этого при входе в любую процедуру в начале области свободной памяти отводится 2 слова для связующей информации, состоящей из специальных управляющих слов:
При вызове процедуры Q принята следующая последовательность операций:
Выход из процедуры осуществляется командой “ВОЗВРАТ”, при этом:
Разработчиками принята точка зрения, согласно которой блок является частным случаем процедуры без параметров, у которой описание и вызов находятся в одном и том же месте программы.
Следовательно, каждый вход в блок сопровождается внесением на вершину стека двух слов — МКС & УСВ и имитацией вызова процедуры. Поскольку параметров нет, всё делается сразу.
Для блока выделяется в стеке область под локальные переменные и создается дескриптор под эту область плюс предыдущие 2 слова с контекстом.
Однако, блок отличается от полноценной функции тем, что в нём доступны переменные из вышестоящих блоков той же функции. Как же это обеспечить?
Данная проблема была решена организацией стека дескрипторов. Как мы помним, у нас в наличии 32 дескриптора, первые 3 из которых зарезервированы. Остальные используются как стек. Т.е. при входе в блок мы наращиваем текущий лексикографический уровень (для этого есть регистр уровня), при выходе из блока, уменьшаем его. Итого, максимально возможный уровень вложенности блоков — от 30 для простых смертных до 32 для операционной системы.
Тут возникают проблемы — пусть мы из блока с уровнем вложенности N функции Q вызываем функцию P со своим деревом блоков. Если ничего не предпринять, то дескрипторы блоков (в базовых регистрах) будут перезаписаны и возврат из P произойдет в неработоспособное состояние.
Естественное место, куда можно сохранить содержимое базовых регистров — контексты блоков в стеке. На самом деле даже сохранять ничего не нужно, содержимое базовых регистров можно заново воссоздать при возврате:
Поддержка блочных языков выглядит довольно громоздкой. Кроме того, механизм базовых регистров имеет двойственную природу — с одной стороны, это механизм разграничения операционной системы, библиотек и конечных программ. А с другой стороны — стек дескрипторов блоков. Почему так получилось?
Из за аппаратной защиты памяти. Каждому блоку соответствует свой дескриптор, стек блоков соответствует стеку дескрипторов.
Почему нельзя было обойтись единым дескриптором для всей функции? По всей видимости потому, что тогда при входе в функцию пришлось бы выделять локальную память для самого худшего случая.
Например:
procedure p;
begin
integer i;
...
begin
integer array s [1:1000];
...
end
...
end
даже если внутренний блок посещается крайне редко, нам тем не менее пришлось бы каждый раз при вызове P выделять под локальные переменные память для 1001 целого, а не 1 фактически необходимого. В условиях, когда память является весьма дорогим ресурсом, это весомый аргумент.
Но почему не сделать для функции дескриптор от МКС функции до конца стека?
Потому что фактически это будет отказ от аппаратной защиты памяти (на 50% :). Кроме того, возможно, сегмент стека умел (или планировалось, что будет уметь) расширяться при переполнении, тогда у него просто нет конца.
Справедливости ради, на современных “Эльбрусах” реализован (в целях безопасности, по-видимому) второй аппаратный стек для хранения информации возврата [9]. С помощью такого механизма вышеописанная защита реализуется куда как более элегантно. Правда, современные “Эльбрусы” имеют мало общего с предметом данной статьи.
Вот мы и добрались до конца. При этом рассмотрели основные архитектурные особенности “Эльбрусов”. Автор намеренно не касался некоторых аспектов, например, работы с периферией, устройства файловой системы … т.к. за истекший период всё настолько сильно изменилось, что (с точки зрения автора) представляет интерес с почти археологической точки зрения — “интересно, ну и как же они выкручивались в то время то?”.
А вот, некоторые именно архитектурные идеи, заложенные в комплекс, не потеряли актуальности и по сей день. Например, теговая система продолжает жить в “эльбрусах” современных. Жаль, что идея суперскалярного стекового процессора [23] не прижилась, хотя концептуально она (на взгляд автора, по крайней мере) стройнее и проще, чем идея регистровой суперскалярной архитектуры или архитектур с явным параллелизмом.
В любом случае, на момент своего появления “Эльбрус” несомненно был на самом острие прогресса, причем его создатели прокладывали свой собственный путь в будущее, опираясь, конечно, на мировой опыт, выдвигали и реализовывали оригинальные идеи.
Дальнейшее развитие комплекса его создатели видели [2, стр 201] в том числе и в использовании конвейеризированного векторного сопроцессора (который существовал и на реальных задачах показывал производительность в 80 Mflops [2, стр 166]), что вполне укладывается в наши сегодняшние представления.
[1] Масич Г.Ф. лекции [24]
[2] Сборник статей В.С Бурцева (руководитель проекта, главный по аппаратной части) [25]
[3] WIKI статья про Эльбрусы [26]
[4] www.osp.ru/os/2009/02/7314081 [27]
[5] www.ixbt.com/cpu/e2k-spec.html [28]
[6] здесь интерес представляют комментарии Погорилого [29]
[7] www.pvsm.ru/programmirovanie/106969 [30]
[8] www.caesarion.ru/warrax/w/warrax.net/88/elbrus.html [31]
[9] www.mcst.ru/files/511cea/886487/1a8f40/000000/book_elbrus.pdf [32]
Автор: zzeng
Источник [33]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/stek/202630
Ссылки в тексте:
[1] 133 серия: http://www.155la3.ru/k133.htm
[2] ТТЛ: https://ru.wikipedia.org/wiki/%D0%A2%D1%80%D0%B0%D0%BD%D0%B7%D0%B8%D1%81%D1%82%D0%BE%D1%80%D0%BD%D0%BE-%D1%82%D1%80%D0%B0%D0%BD%D0%B7%D0%B8%D1%81%D1%82%D0%BE%D1%80%D0%BD%D0%B0%D1%8F_%D0%BB%D0%BE%D0%B3%D0%B8%D0%BA%D0%B0
[3] 100-я серия: http://www.155la3.ru/k100.htm
[4] ЭСЛ: https://ru.wikipedia.org/wiki/%D0%AD%D0%BC%D0%B8%D1%82%D1%82%D0%B5%D1%80%D0%BD%D0%BE-%D1%81%D0%B2%D1%8F%D0%B7%D0%B0%D0%BD%D0%BD%D0%B0%D1%8F_%D0%BB%D0%BE%D0%B3%D0%B8%D0%BA%D0%B0
[5] Motorola: https://ru.wikipedia.org/wiki/Motorola
[6] TI: https://en.wikipedia.org/wiki/Texas_Instruments
[7] К565РУ3В: https://ru.wikipedia.org/wiki/%D0%9A565%D0%A0%D0%A33
[8] NMOP: https://ru.wikipedia.org/wiki/N-%D0%9C%D0%9E%D0%9F
[9] барабаны: http://ru.wikipedia.org/wiki/%D0%9C%D0%B0%D0%B3%D0%BD%D0%B8%D1%82%D0%BD%D1%8B%D0%B9_%D0%B1%D0%B0%D1%80%D0%B0%D0%B1%D0%B0%D0%BD
[10] DBM: https://en.wikipedia.org/wiki/Dbm
[11] стековый процессор: https://en.wikipedia.org/wiki/Stack_machine
[12] дерева разбора: https://ru.wikipedia.org/wiki/%D0%90%D0%B1%D1%81%D1%82%D1%80%D0%B0%D0%BA%D1%82%D0%BD%D0%BE%D0%B5_%D1%81%D0%B8%D0%BD%D1%82%D0%B0%D0%BA%D1%81%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%BE%D0%B5_%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%BE
[13] OoO: https://ru.wikipedia.org/wiki/%D0%92%D0%BD%D0%B5%D0%BE%D1%87%D0%B5%D1%80%D0%B5%D0%B4%D0%BD%D0%BE%D0%B5_%D0%B8%D1%81%D0%BF%D0%BE%D0%BB%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5
[14] суперскалярность: https://ru.wikipedia.org/wiki/%D0%A1%D1%83%D0%BF%D0%B5%D1%80%D1%81%D0%BA%D0%B0%D0%BB%D1%8F%D1%80%D0%BD%D0%BE%D1%81%D1%82%D1%8C
[15] спекулятивное исполнение кода: https://ru.wikipedia.org/wiki/%D0%9F%D0%B0%D1%80%D0%B0%D0%BB%D0%BB%D0%B5%D0%BB%D0%B8%D0%B7%D0%BC_%D0%BD%D0%B0_%D1%83%D1%80%D0%BE%D0%B2%D0%BD%D0%B5_%D0%BA%D0%BE%D0%BC%D0%B0%D0%BD%D0%B4
[16] scoreboarding: https://en.wikipedia.org/wiki/Scoreboarding
[17] переименования регистров: https://en.wikipedia.org/wiki/Register_renaming
[18] регистровых окон: https://ru.wikipedia.org/wiki/%D0%A0%D0%B5%D0%B3%D0%B8%D1%81%D1%82%D1%80%D0%BE%D0%B2%D0%BE%D0%B5_%D0%BE%D0%BA%D0%BD%D0%BE
[19] когерентности кэша: https://ru.wikipedia.org/wiki/%D0%9A%D0%BE%D0%B3%D0%B5%D1%80%D0%B5%D0%BD%D1%82%D0%BD%D0%BE%D1%81%D1%82%D1%8C_%D0%BA%D1%8D%D1%88%D0%B0
[20] спинлоками: https://ru.wikipedia.org/wiki/Spinlock
[21] тупиков: https://ru.wikipedia.org/wiki/Deadlock
[22] уровень привилегий х86: https://en.wikipedia.org/wiki/Privilege_level
[23] суперскалярного стекового процессора: https://habrahabr.ru/post/278575/
[24] Масич Г.Ф. лекции: http://www2.icmm.ru/~masich/win/lexion/elbrus2/elbrus2.htm
[25] Сборник статей В.С Бурцева (руководитель проекта, главный по аппаратной части): http://www.computer-museum.ru/books/Burcev_elbrus.pdf
[26] WIKI статья про Эльбрусы : https://ru.wikipedia.org/wiki/%D0%AD%D0%BB%D1%8C%D0%B1%D1%80%D1%83%D1%81_(%D0%BA%D0%BE%D0%BC%D0%BF%D1%8C%D1%8E%D1%82%D0%B5%D1%80)
[27] www.osp.ru/os/2009/02/7314081: http://www.osp.ru/os/2009/02/7314081/
[28] www.ixbt.com/cpu/e2k-spec.html: http://www.ixbt.com/cpu/e2k-spec.html
[29] здесь интерес представляют комментарии Погорилого: http://dm-kalashnikov.livejournal.com/79346.html
[30] www.pvsm.ru/programmirovanie/106969: http://www.pvsm.ru/programmirovanie/106969
[31] www.caesarion.ru/warrax/w/warrax.net/88/elbrus.html: http://www.caesarion.ru/warrax/w/warrax.net/88/elbrus.html
[32] www.mcst.ru/files/511cea/886487/1a8f40/000000/book_elbrus.pdf: http://www.mcst.ru/files/511cea/886487/1a8f40/000000/book_elbrus.pdf
[33] Источник: https://habrahabr.ru/post/313376/?utm_source=habrahabr&utm_medium=rss&utm_campaign=best
Нажмите здесь для печати.