Sem2

Регистры Intel Itanium

В процессоре есть следующие регистры:
1. General Registers (GR): Это целочисленные регистры, разрядностью 64 бита. Всего в процессоре присутствует 128 регистров (gr0 – gr127). gr0 всегда равен 0 и доступен только для чтения. Чаще всего он используется при сравнении чисел с 0, чтобы не приходилось каждый раз загружать 0 в регистр.
gr1 – Global Data Pointer. Oн указывает на кучу (pile).
Регистры gr8 – gr11 используются для размещения возвращаемого значения при выходе из функций.
Регистры gr0 – gr31 – статические регистры. Они видны изо всех функций, и не являются стековыми (stacked registers). Начиная с r32 идет стек регистров.

2. Floating registers (FR): Это регистры для представления чисел с плавающей точкой, разрядность 82 бита. Всего регистров 128 (fr0 – fr127). fr0 и fr1 – регистры только для чтения, в них хранятся значения 0 и 1 соответственно. fr8 и fr9 используются для возврата значений.

3. Predicate Registers (PR): Это регистры предикатов. Всего регистров 64 (pr0 – pr63), разрядность – 1 бит. Но PR может быть использован как 1 64-битный регистр. pr0 доступен только для чтения и всегда равен 1. Регистры pr0 – pr15 – статические. Начиная с pr16 регистры могут вращаться.

4. Branch registers (BR): Это регистры, используемые для хранения адреса перехода. Всего их 8 (br0 – br7), разрядность – 64. В регистре BR0 всегда хранится адрес возврата.

5. Application Registers (AR): набор регистров специального назначения. Нам понадобятся:
ar.pfs – адрес структуры, описывающей текущий фрейм
ar.lc – счетчик цикла
ar.ec – счетчик эпилога

6. Instruction Pointer (IP): 64-разрядный регистр. Хранит адрес бандла команды, исполняемой в данный момент.

7. Control Frame Mark (CFM). Это 1 64-битный регистр. Используется для описания текущего регистрового окна и вращения регистров в нем.

8. Performance Monitor Data Registers (PMDR): регистры данных для Performance Monitor.

9. Advanced Load Allocation Table (ALAT): в общем, к регистрам, насколько я понял, эта таблица не относится, но на семинаре упоминалась именно в этом контексте. Назначение – таблица для data speculation
Более детальное описание регистров – на странице 5 1-го vol’а; ALAT – на стр. 55.

Типы инструкций:

В IA64 есть несколько типов инструкций:
A (арифметические)
M (инструкции работы с памятью)
I (инструкции работы с целыми числами)
F (инструкции работы с числами с плавающей точкой)
B (инструкции ветвления)
L (работа с длинными целыми, long) //насколько я понял

Так же есть несколько типов устройств, и, соответственно, портов для исполнения этих инструкций; рассматривались типы M, I, F, B, A и Mul. Команды классов M, F, I и B используют только соответствующие им классы портов. Команды классов A и L могут исполняться на разных типах:
A на M и I
L – на B и F
Портов каждого типа в процессоре несколько, и при планировании одного такта порты раздаются поочередно, и если, даже внутри одного бандла, порта команде не хватило (все порты, на которых команда могла быть выполнена, уже распределены для выполнения предыдущих команд), в данном такте выполняются только предыдущие команды, а планирование следующего такта начинается с нее.

Типы и количество портов:
M - 4
I - 2
B - 3
F - 2

Количество устройств:
I – 2
A – 6 //только непонятно, зачем тогда арифметические операции используют чужие порты если у них 6 своих? (больше 6 инструкций за раз исполняться все равно не может) — Тут речь надо вести все же об устройствах. Портов значительно меньше, чем собственно устройств. Чтобы составить более ясное впечатление о работе конвеера надо вспомнить что не все команды исполняются за 1 такт. Т.е. команда распределившись на определенный порт в конце концов попадает на конкретное устройство и при отсутствии зависимостей и достаточном количестве устройств код обрабатывается конвеером по 2 бандла за такт, а реально исполнение каждой команды может занимать много тактов. Планировать команды так, чтобы скрыть задержки и обеспечить плавное течение код через конвеер - задача планировщика.

M – 4 (при чем запись может производиться только через M0 и M1, а чтение – через любой)
Не совсем так: целочисленное чтение через М0 и М1, целочисленная запись через М2 и М3, вещественное чтение через любой порт и запись через М2 и М3. Вещественные advanced load только через М0 и М1.
F – 2
B – 3
Mul – 6 (устройства для работы с мультимедиа)

Memory subsystem
простая схема:
Memory -> Bus -> L3Cache -> L2Cache -> L1I и L1P (2 отдельных КЭШа, для инструкций и данных)

Размеры: L3 – 3/6/9/12 MB (мы будем работать с 9-метровым кэшем)
L2 – 256K
L1I = L1D – 16K

Задержка при доступе в кэш:
L1 – 1; (т.е. работает на частоте процессора )
L2 – 5+ тактов
L3 – 14+ тактов

Подгружать данные процессор может автоматически, но подгрузкой можно управлять с помощью команды lfetch.[…] (подгрузить указанную область в кэш)
Подсказки (hints):
.nt0 – подгрузить в L1
.nt1 – подгрузить в L2
.nt2 – тоже подгрузить в L2, но некоторым особым способом (каким именно я недопонял)
.nta – подгруить сразу в L2 минуя L3.

в итоге команда будет выглядеть так:
lfetch.nt1[…]

Зачем нужен .nta?:
обычно данные сначала подгружаются в L3, а только потом в L2. Допустим, у нас есть 2 вложенных цикла: внешний использует совсем немного памяти, и внутренний – каждый раз последовательно перебирает объем, больший, чем размер L3. в итоге, куда бы не подгружались данные, они затрут данные внешнего цикла, и их придется каждый раз заново тянуть из памяти. Выход – оставить данные внешнего цикла в L3 и подгружать данные внутреннего цикла сразу в L2.

Конвейер в IA:
Любой конвейер имеет несколько стадий:
-Fetch: подгрузка инструкции из памяти и управление IP
-Read: чтение текущего архитектурного состояния процессора
-Execute: само исполнение команды
-Update: обновление состояния системы
--
Заметим, что архитектурное состояние – это состояние, которое видно в качестве интерфейса исполняемой программы. Оно отличается от физического состояния тем, что в него не входят конвейеры, таблицы виртуальной памяти и прочие устройства, используемые только внутри процессора и скрытые от обычных программ.
--

Собственно конвейер итаниума состоит из 9 стадий:
1) IPG – Instruction pointer generation. На этой фазе из КЭШа читается команда, и в IP записывается вычисленное значение следующей команды, которая будет исполнена. IP не всегда увеличивается на 1, новое значение вычисляется отдельно, по своему алгоритму, учитывающему предсказание переходов.
2) ROT – загружает пары команд из двух пришедших бандлов в буфер. i-я пара – это пара из i-х команд каждого бандла.
3) Буфер на 24 пары команд
4) EXP (Expand): распределяет инструкции по портам
5) REN (Rename): транслирует виртуальные регистры в реальные
6) REG: подгружает нужные данные из памяти в кэш
7) EXE: непосредственно исполнение
8) DET: проверка на наличие ошибок, и, соответственно, генерация исключения, или изменение NAT
9) WRB(writeback): если все выполнилось нормально, записывает изменения в систему.

Эти 9 этапов делятся на 3 блока:
- Front end (FE): IPG и ROT
- Instruction Buffer (IB): собственно, он и есть.
- Back End(BE): EXP – WRB.

Естественно, работа конвеера в итаниуме не лишена проблем:
- Если на момент исполнения команды нужные данные еще не подгрузились, стадия REG будет ждать, пока они загрузятся. В это время буфер команд переполнится, и конвейер будет стоять. А когда команда таки выполнится, его придется заново разгонять, что потребует существенное количество времени.
- Если мы неправильно предсказали, куда будет передано управление, команды, содержащиеся в буфере будут бесполезными, и буфер придется обнулять и подгружать заново. Это тоже требует дополнительного времени.

Картинки сделаю в ближайшие день-два.
// MrDAN

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-Share Alike 2.5 License.