Обзор микроархитектур современных десктопных процессоров. Часть 1
Страница 11. AMD Athlon 64 / Opteron (K8)


AMD Athlon 64 / Opteron (K8)

В процессоре K8 применена схема с предварительным декодированием (предекодированием) x86-инструкций перед помещением их в I-кэш. Назначение этого предекодирования — определить границы и положение кода операции в каждой x86-инструкции, а также определить тип инструкции — простой или сложный. Простая инструкция будет преобразована в один или два МОПа в «простом» декодере (DirectPath, DP), сложная — в три или более МОПов в «сложном» декодере (VectorPath, VP). Для запоминания информации о разметке в I-кэше имеются дополнительные биты — по три бита на каждый байт инструкций. Таким образом, в дополнение к 64 Кбайтам для хранения исходных x86-инструкций в I-кэше имеется также 24 Кбайт для хранения информации о разметке. Предекодирование ведётся в небольшом темпе, не более 4 байтов за такт.

Из I-кэша инструкции считываются выровненными блоками по 16 байтов за такт, с опережающей предвыборкой. Благодаря наличию информации о разметке сразу после считывания блока происходит выделение инструкций из буфера и отсылка в соответствующие устройства декодирования — «простое» (DirectPath) или «сложное» (VectorPath). За один такт в простое устройство может быть отправлено до 6 инструкций — они накапливаются в небольшом входном буфере. Из этой очереди инструкции поступают в три параллельно работающих канала декодирования. Если во входном потоке есть сложная инструкция, то она направляется непосредственно в сложное устройство.

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

В результате на выходе из декодера в каждом такте образуется одна группа, содержащая до трёх МОПов. Каждая такая группа содержит МОПы, произведённые либо простым, либо сложным устройством декодирования — то есть в одной группе МОПы из разных устройств не смешиваются. Это может привести к неполному заполнению последней группы МОПов, вышедшей из простого либо из сложного устройства. МОПы выходят из декодера в порядке, соответствующем порядку исходных x86-инструкций.

Сформированная группа МОПов поступает в буфер переупорядочения и в дальнейшем отслеживается как единое целое. В блок отставки выполненные МОПы могут поступать также только в составе исходной группы. Помимо удобства отслеживания внеочередного исполнения и отставки, объединение МОПов в фиксированные группы имеет ещё одну цель: позиция МОПа в группе привязана к номеру очереди планировщика и функционального устройства, в которые этот МОП будет отправлен. Это относится к целочисленным и адресным операциям (ALU/AGU). Для операций арифметики с плавающей точкой (FPU) такой привязки нет — группа, содержащая такие МОПы, просто копируется целиком в новый элемент очереди планировщика FPU. Статическая привязка позиции МОПа к номеру соответствующей очереди или устройства, в сочетании с отслеживанием инструкций в составе групп, позволяет упростить организацию подсистемы внеочередного исполнения.

К числу простых инструкций, порождающих два МОПа (DirectPath Double, DD), относятся все упакованные инструкции SSE, а также инструкции целочисленного умножения и некоторые другие. Для большинства таких инструкций нет ограничений по размещению в группах — например, два МОПа упакованной инструкции SSE могут оказаться в соседних группах. Однако МОПы инструкции целочисленного умножения должны обязательно размещаться в одной группе в двух первых позициях, так как они исполняются совместно в двух первых устройствах ALU. Подобное требование также может привести к неполному заполнению группы.

Для сложных инструкций (VectorPath) требуется, чтобы они обрабатывались в блоке отставки операций как единое целое, без смешивания с другими (простыми) инструкциями. Поэтому декодер не объединяет МОПы простых и сложных операций в одной группе, что приводит к потерям на фрагментацию. Правда, такие сложные инструкции в микроархитектуре K8 довольно редки.

Помимо перечисленных случаев, группа МОПов может оказаться не заполненной до конца, если прерывается входной поток инструкций. Это может произойти при отсутствии следующего блока инструкций в I-кэше, при неправильном предсказании условного перехода, при отсутствии адреса перехода в таблице BTB, а также и при правильном предсказании в случае, если инструкции считывались из кэша с недостаточным опережением.

Таким образом, схему работы декодера в процессоре K8 можно обозначить как «2-2-2 / >2». В сравнении с предшествующим процессором K7 декодер инструкций был значительно усовершенствован: в старом процессоре декодер работал по схеме «1-1-1 / >1» и обрабатывал только два класса инструкций - простые (DirectPath), порождающие один МОП, и сложные (VectorPath), порождающие два и более МОПов. К последним, в частности, относились все упакованные инструкции SSE, что приводило к заметному снижению эффективности работы декодера.

Важной особенностью процессора K8 (и его предшественника K7) является отход от принципа максимального упрощения МОПов, в которые преобразуются исходные x86-инструкции. Этот принцип предполагал, что МОПы должны быть RISC-подобными — в частности, что операции обработки должны отделяться от операций обращения в память. Следование данному принципу упрощало организацию процессора, но приводило к увеличению числа порождаемых и обрабатываемых МОПов примерно в 1.3-1.5 раза. В процессорах K7/K8 МОПы являются комбинированными и могут содержать два элементарных действия — арифметическое и адресное. Разделение на эти действия происходит при запуске МОПа на исполнение. Таким способом реализованы операции типов Load-Op, Op-Store и Load-Op-Store.

Данный подход был позднее заимствован и частично реализован в процессоре Intel P-M (и последующих) для операций типа Load-Op (под названием «слияние микроопераций»).

В связи с тем, что разметка x86-инструкций производится заранее, перед помещением в I-кэш, в декодере не накладывается никаких ограничений на их длину и структурную сложность. В частности, не ограничивается число префиксов в одной инструкции, что позволяет использовать фиктивные префиксы для выравнивания инструкций там, где это необходимо. Например, для бесперебойной работы декодера в максимальном темпе (три инструкции за такт) в процессоре K7 рекомендуется размещать по три x86-инструкции в выровненном блоке (бандле) длиной 8 байт. Для операций с плавающей точкой x87 можно использовать префикс REP, который не оказывает на них никакого влияния. Пример кода, в котором применение фиктивных префиксов могло бы оказаться необходимым, показан на Рис. 2 (правда, в данном примере инструкции уже выровнены правильным образом). В процессоре K8 рекомендация о размещении инструкции в 8-байтовых бандлах снята, однако могут потребоваться другие типы выравнивания.

Таким образом, процессор K8 имеет достаточно гибкий и эффективно реализованный трёхканальный декодер. Организация с предекодированием инструкций до помещения их в I-кэш позволяет уменьшить длину конвейера и снять ограничения на структурную сложность инструкций, декодируемых в полном темпе. Однако необходимость в предекодировании может снизить темп считывания потока инструкций из L2-кэша или памяти. Кроме того, предекодированию подвергаются только те участки кода, по которым проходит трасса исполнения. Поэтому участки, расположенные после «точек выхода» из этой трассы (то есть после совершённых инструкций перехода) или перед «точками входа» в трассу, могут оказаться неразмеченными либо неправильно размеченными. Последующее исполнение инструкций из этих участков кода потребует предекодирования «на ходу» с потерей темпа работы.

По завершении декодирования группа МОПов помещается в буфер переупорядочения и в очереди планировщика. Одновременно производится переименование (переназначение) регистров результатов для этих МОПов. Для этого используются отдельные наборы внутренних (физических) регистров для целочисленной/адресной арифметики ALU/AGU и для арифметики с плавающей точкой FPU. Физические регистры ALU/AGU приписаны соответствующим позициям буфера переупорядочения, и число таких регистров равно длине буфера (72 позиции). Также имеется определённое количество дополнительных регистров такого же типа, предназначенных для хранения последних значений результатов и используемых для ускорения доступа к данным. Для внутренних регистров FPU применяется более сложная динамическая схема переназначения, число таких регистров равно 120 (включая архитектурные). Для хранения одного 128-битного регистра XMM используются два внутренних регистра FPU.

 
« Предыдущая статья   Следующая статья »