МЕТОДЫ ПОВЫШЕНИЯ ПРОИЗВОДИТЕЛЬНОСТИ СУПЕРСКАЛЯРНОГО RISC-ПРОЦЕССОРА С.И. Аряшев, М.Е. Барских, К.С. Бычков Научно-исследовательский институт системных исследований РАН, [email protected] Конвейер процессора При разработке модели RISC-процессора за основу был взят классический 5-стадийный конвейер [1, 2]. Был проведен анализ конфликтов и загруженности стадий, после которого было принято решение углубить конвейер на 2 стадии. Была добавлена стадия работы microTLB команд (iTLB) и вынесена в отдельную стадию процедура чтения данных из регистрового файла, так как в ней дополнительно происходит обработка обратных связей по данным (bypass). Реализуемый вариант конвейера показан на рис.1. На стадиях 4-7 возможно параллельное выполнение целочисленных и вещественных команд. clk 1 Стадии iTLB iTLB 2 IF 3 PID 4 5 6 7 RFA 1 EXE 1 MA 1 WB 1 RFA 2 EXE 2 MA 2 WB 2 ID Доступ в microTLB команд iTLB access IF Instruction fetch Получение команд PID Instruction predecode Предворительное декодирование команд ID Instruction decode Декодирование команд RFA Register file access Чтение данных из регистрового файла EXE Execute Выполнение команды/вычисление адреса MA Memory access Доступ к памяти (чтение/запись) WB Write back Запись результатов в регистровый файл Рис. 1. Реализованный 7-стадийный конвейер (штриховкой показаны измененные стадии по сравнению с классическим 5-стадийным конвейером) Первоначальный вариант предусматривал реализацию процессора с ограниченной суперскалярностью (одновременная выдача на выполнение целочисленных и вещественных команд). На этом этапе были отлажены модели функциональных блоков и получена модель, которая в дальнейшем была принята за эталонную при реализации различных схем повышения производительности. В данной статье приведены решения, примененные при разработке этой модели. Основной упор сделан на повышение производительности буфера команд и интерфейса между буфером команд, кэш-памятью команд и блоком вещественной арифметики. Конфликты и зависимости При анализе структурных конфликтов учитывалась логическая сложность блоков. В модели реализовывался наборно-ассоциативный кэш (раздельный для команд и данных) и полностью ассоциативный TLB (буфер быстрого преобразования адреса) [12]. Поэтому основным объектом внимания была стадия записи результатов. При выполнении многотактовых команд сложно отследить момент, когда закончились одновременно 2 команды, которые требуют записи в регистровый файл. Для обхода этого конфликта есть следующие пути: жесткая остановка конвейера при выполнении многотактовых команд; добавление к регистровому файлу дополнительного порта для записи; создание «окна записи», в котором фиксируются результаты, поочередно записываемые в регистровый файл; добавление специальных регистров, в которые записываются результаты многотактовых команд. Первый вариант решения проблемы самый простой и не требует никаких дополнительных схем управления. Но он слишком сильно снижает производительность при активном использовании целочисленных команд умножения и деления и совершенно не приемлем для вещественных команд, которые все, за редким исключением (замены знака и получения модуля числа), являются многотактовыми. Второй способ требует анализа регистров-приемников, чтобы не допустить одновременной записи в один и тот же регистр двух результатов. Он не подходит для суперскалярного конвейера, в котором одновременно может завершаться больше двух команд, так 214 как пропорциональное увеличение числа портов записи приведет к сложностям в анализе зависимостей по записи и увеличению времени работы самого регистрового файла. Третий вариант с созданием «окон записи» может одинаково использоваться как в скалярном, так и в суперскалярном конвейере и блоке вещественной арифметики (FPU). Кроме того, это позволяет решить проблему упорядочивания команд при динамическом выполнении, но требует усложнения логики работы обратных связей по данным, чтобы избежать простоя при чтении уже вычисленных, но еще не записанных результатов предыдущих команд. Последний, четвертый, вариант решения с добавлением специальных регистров используется для того, чтобы разделить выполнение однотактовых и многотактовых команд, поскольку в наборе целочисленных команд только команды умножения и деления выполняются более одного такта. Это позволит сделать «независимыми» многотактовые и однотактовые команды. Платой за такое решение будет добавление команд чтения и записи этих регистров, но при этом не будет блокировок и зависимостей по данным. Компилятор может качественно спланировать размещение команд программы, зная количество тактов, необходимых на выполнение длинных команд, а логика обнаружения конфликтов будет максимально упрощена – необходимо только отследить обращение к этим дополнительным регистрам при выполнении операции умножения/деления. Только в этом случае конвейер будет остановлен. Такое решение применяется в MIPS-архитектуре [5, 6], где введены два дополнительных регистра HI и LO для записи результатов, и четыре команды обмена с ними: Таблица 1 Команды чтения/записи регистров Hi/Lo Регистр HI LO Действие MTHI MTLO Запись MFHI MFLO Чтение Кроме того, для возможности выполнения независимых команд, следующих за командами умножения/деления, в MIPS-архитектуре отсутствует исключение «деление на 0» (divide by zero). Проверку на нулевой делитель компилятор вставляет автоматически сам. А емкости общего 128разрядного регистра (Hi+Lo) гарантировано хватает для хранения результата 64-разрядного умножения. Эта схема и была реализована в разрабатываемой модели. Между командами программы возможны 3 типа зависимостей. Это действительная (true) зависимость, антизависимость (false) и зависимость по выходу (output). Зависимость RAW (чтение после записи): чтение операндов команды должно начаться не раньше завершения предыдущей операции, от которой она зависит. В скалярном конвейере такая зависимость может возникать, только если команда i1 многотактовая, и именно из-за этой зависимости происходит блокировка конвейера. Для снятия зависимостей между однотактовыми командами в ALU применяются обратные связи по данным. Это позволяет не ждать момента, когда первая команда запишет свои данные в регистровый файл (3 такта), а брать их из обратных связей тех стадий, через которые проходит вычисление (EXE, MEM, WB). Зависимость WAR (запись после чтения): запись результатов команды не должна произойти раньше чтения их предыдущей командой. Зависимость WAW (запись после записи): запись результатов команды не должна произойти раньше записи результатов предыдущей команды. Такие зависимости проявляются только в неблокирующемся суперскалярном конвейере, в котором реализовано планирование команд и их динамическое выполнение (выдача на исполнение и завершение в произвольном порядке, отличном от заданного в программе). В простом конвейере с блокировкой стадий такие зависимости не возникают. Но кроме регистровых зависимостей, кратко перечисленных выше, в программе может возникать зависимость по данным, записываемым в память. Для оптимизации записи данных в память и их повторного чтения в процессоре используется буфер записи в память (store buffer). Он позволяет отложить непосредственно запись в память данных до тех пор, пока не освободится системная шина. А команды загрузки данных (LOAD), просматривая этот буфер, читают из него недавно записанные данные, в свою очередь, не загружая шину своим запросом. Общая структура модели Общая структура модели изображена на рис. 2. На нем серым цветом выделены регистры, стрелками показаны стадии конвейера. Регистровый файл при чтении работает как комбинационная схема, а при записи – как регистр. Увеличение глубины конвейера сказалось на выполнении команды из слота задержки команды ветвления: в таком конвейере требуется 4 команды, выполняющиеся после команды ветвления, чтобы не было простоя конвейера. Количество тактов простоя равно числу стадий конвейера между его началом (стадией выборки команд) и стадии, на которой принимается решение о переходе (не включая саму эту стадию). Поскольку вычисление условия перехода происходит на стадии EXE, то требуется именно 4 команды (из них одна – слот задержки, уже определенный в спецификации набора команд). Вычисление условия на более ранней стадии 215 конвейера невозможно, так как только на стадии RFA получаются операнды для сравнения, и вычисление в нем же условия невозможно (стадия еще нагружена обработкой обратных связей по данным). Instruction Address dCache MEM iTLB iCache Memory address Memory data iTLB iCache Instruction WB dTLB PC control Instruction fields ID Instruction decode EXE Register file RFA ALU bypass Data 1 ID Data 2 Decoded Instruction Decoded Instruction WB EXE ALU EXE ALU result / Memory address RFA ALU result MEM Рис. 2. Общая структура модели с выделением функциональных блоков и делением на стадии конвейера (показана только целочисленная часть процессора) В то же время, углубление конвейера не отразилось на выполнении слота задержки команды LOAD, так как между стадиями EXE и MEM новых стадий не добавилось. Для многотактовых целочисленных команд введены два отдельных регистра назначения, в которых сохраняются их результаты (на рис. 7 не показаны названия HI, LO). Блок вещественной арифметики реализован отдельным независимым сопроцессором и не показан на рисунке. Схема общего декодирования в буфере команд (стадия ID, блок «instruction decode») контролирует внутренний буфер окна выполнения и распределяет команды по потокам, детальное декодирование команд происходит непосредственно перед выполнением в исполняющих конвейерах (на стадии RFA, в блоке «ALU decode»). Таким образом, хотя конвейер имеет больший штраф за неверное предсказание перехода, увеличение количества стадий позволило уменьшить время выполнения каждой из них в отдельности, и, соответственно, увеличить тактовую частоту по сравнению с классическим конвейером. Применение же схем предсказания ветвления позволит существенно уменьшить простои конвейера. Целочисленные и вещественные команды выдаются на выполнение одновременно (кроме команд пересылки данных). Для хранения считанных из кэш-памяти команд предназначен внутренний буфер на 4 команды, из которого попарно выбираются команды на декодирование (не показан на рисунке). Поток команд и занятость ресурсов Управление потоком команд и загрузкой конвейера, а так же обнаружение и устранение конфликтов, возложено на буфер команд. В его функции входит управление счетчиком команд (PC), формирование запроса на выборку команд, их декодирование и выдачу на выполнение. Поскольку 216 именно буфер команд сталкивается со всеми возможными конфликтами и остановками конвейера, еще раз перечислим их с краткими комментариями: 1. Конфликты по ресурсам: 1.1. Доступ на чтение/запись регистров Hi/Lo при выполняющейся команде умножения/деления (имеются в виду команды пересылки регистров). Блокировка конвейера до окончания вычислений. 1.2. Команды деления и умножения не конвейеризированы. Следующая команда деления (или умножения) будет выдана на выполнение только после окончания предыдущей. 2. Конфликты по данным: 2.1. Для целочисленных многотактовых команд конфликт происходит только в регистрах Hi/Lo. Сводится к структурному конфликту 1.1. 2.2. Команда LOAD (как целочисленная, так и вещественная) не имеет обратной связи со стадии EXE, поскольку для её выполнения требуется стадия MEM. Если следующей за командой LOAD команде требуется её результат, то происходит остановка на 1 такт. 2.3. Выполнение команд загрузки/сохранения вещественных данных требует готовности как данных в ALU (для вычисления адреса), так и FPU. При занятости хотя бы одного из них происходит блокировка до момента возможности вычисления. 3. Конфликты по управлению: 3.1. Используется слот задержки. Подтверждение перехода происходит на стадии EXE. Начало новой выборки команд возможно только после завершения обработки предыдущего (уже выставленного) запроса. 3.2. Следующие за командой ветвления команды не выдаются на выполнение до принятия решения о переходе (или об отсутствии перехода). 4. Дополнительные остановки при работе: 4.1. При выполнении команд LOAD/STORE на стадии MEM происходит обращение в dTLB (поднабор общей таблицы TLB, предназначенной для преобразования адресов данных). Непопадание вызывает остановку на один такт конвейера работы с памятью от стадии ID включительно (происходит доступ в jointTLB). Непопадание в неё вызывает исключение, которое отменяет все последующие выданные на выполнение команды. 4.2. Непопадание в iTLB вызывает задержку на один такт в получении команд, но не влияет на работу остального конвейера (конвейер не блокируется). Как и в случае с обработкой данных, происходит доступ в jointTLB; промах вызывает исключение, которое не приводит к отмене ранее выданных на выполнение команд. Для детектирования конфликтов буфер команд имеет интерфейс с блоком целочисленной арифметики (ALU), блоком вещественной арифметики (FPU) и блоком управления памятью (MMU); учитывает занятость блока деления (так как команда деления выполняется нефиксированное число тактов) и регистров Hi/Lo, зависимость команды от предыдущей, готовность FPU к выполнению следующей команды. Буфер команд должен декодировать все возможные комбинации команд, чтобы не возникало дополнительных простоев конвейера, связанных с невозможностью обработать определенную комбинацию. При реализации декодера команд следует провести оценку необходимых ресурсов для обработки каждой ситуации и влияния остановок на различных стадиях конвейера на работу всего буфера команд. Как уже отмечалось, чтобы избежать зависимостей по данным в целочисленных командах, были добавлены специальные регистры Hi/Lo, а для обмена с ними – четыре команды. Для обнаружения конфликта при доступе к этим регистрам буфер команд должен декодировать команды: MTHI, MTLO, MFHI, MFLO (при этом нужно декодировать только сам тип этих четырех команд; знать, какая именно это команда для обнаружения конфликта не обязательно). Команда деления (нужна также для определения занятости самого блока деления). Команды умножения: отдельно стробы для 32- и 64-разрядного умножения, так как эти операции выполняются фиксированное, но разное число тактов. При выдаче на выполнение команд умножения или деления выставляется флаг занятости регистров Hi/Lo и флаг занятости соответствующего блока. При декодировании следующей команды, проверяется её тип и, если она требует доступа к этим регистрам (или блокам умножения/деления), то её выдача на выполнение блокируется, а конвейер от стадии iTLB до стадии ID останавливается до завершения ранее выданной команды умножении/деления. Флаг занятости блока умножения сбрасывается через фиксированное количество тактов, флаг занятости блока деления – по стробу готовности результатов деления из ALU. Декодируются все команды LOAD, и при выдаче их на выполнение запоминается номер регистра назначения и строб команды (отдельно для целочисленных и вещественных команд). При декодировании следующей команды номер её регистра-источника сравнивается с запомненным и маскируется стробом (во избежание ложных срабатываний при других зависимых командах). При их совпадении также блокируется выдача на выполнение декодируемой команды. Кроме того, запоминается номер регистра выдаваемой на этом такте команды (или сбрасывается текущий, если не 217 было выдачи из-за остановки). В следующем такте проверка повторяется, но команда выдается на выполнение, так как значение регистра-приемника команды LOAD было сброшено. По такой же схеме декодируются все конфликты, возникающие в конвейере, если решено отказаться от обратных связей из каких-либо стадий (что иногда делается для повышения частоты работы). Особо следует отметить, что, не смотря на унификацию типов команд и их одинаковую длину, не удается добиться того, чтобы во всем наборе команд поле с номером регистра назначения лежало в одном и том же месте кода команды. Это затрудняет обнаружение зависимостей, поскольку требует декодирования наборов команд, у которых поле с номером регистра находится в одном месте; проводить мультиплексирование поля, и только после этого проводить само сравнение, которое и показывает, можно ли запускать команду на выполнение. Данной проблемы можно избежать только увеличением длины команды [8], что скажется на увеличении объема кэш-памяти и разрядности шин (при условии одинаковой пропускной способности). Поскольку блок вещественной арифметики имеет свой собственный регистровый файл, то его можно рассматривать как отдельное независимое функциональное устройство. В самом простом случае, без использования специальных схем повышения производительности, при декодировании команды FPU буфер команд должен проверить, свободно ли устройство для принятия команды на обработку. Для этой цели служит сигнал, формируемый FPU, когда блок готов к принятию на вычисление следующей команды. В противном случае команда на выполнение не выдаётся и конвейер останавливается. Несмотря на потерю производительности, такая логика работы хорошо подходит для процессоров с поддержкой точных прерываний, так как не требует схем восстановления состояния процессора перед исключительной ситуацией. Кроме того, эта предельно простая схема легко реализуется. При возможности одновременной выдачи команд в ALU и FPU, команды пересылки выполняются одновременно в двух блоках, когда FPU готов к выполнению команды. Таким образом, нет рассинхронизации в вычисленном адресе (вычисляется в ALU) и данными, передаваемыми в FPU. Перед выдачей на выполнение таких команд, буфер команд должен отследить готовность FPU и ALU. Для этого используются: 1. Флаг требования остановки: взводится при декодировании команды пересылки. Он блокирует выдачу на выполнение любых команд в ALU и FPU. 2. Флаг готовности ALU: взводится при отсутствии зависимостей по регистрам-источникам для команды пересылки (или LOAD/STORE). Если регистр-источник не готов, флаг не выставляется. 3. Флаг готовности FPU: взводится при выставлении блоком FPU сигнала готовности. Как только выставлены все флаги готовности, происходит выдача на выполнение команды перемещения или загрузки/сохранения. Флаги проверяются каждый такт в момент декодирования команды и при одновременной готовности ALU и FPU задержки в выдачи команды на выполнение не происходит. Работа буфера команд Для того, что бы выдавать на выполнение 2 команды за такт (в рассматриваемом случае в ALU+FPU), буфер команд должен запрашивать из кэш-памяти не менее двух команд. Поскольку считанная пара может содержать команды, не выполняемые параллельно, то буфер команд должен либо выставить запрос к кэш-памяти только на одну команду, либо выдать эти две команды последовательно. Но на обработку запроса требуется 2 такта, а поскольку ситуации, когда команды не могут быть выполнены параллельно, в процессоре с ограниченной суперскалярностью возникают постоянно, было принято решение считывать по одному запросу четыре команды. Для хранения полученных команд используется встроенный буфер, из которого по две команды берутся на декодирование. В случае, если возможно выдать на выполнение только одну команду (номер i), в следующем такте выбираются на декодирование i+1 и i+2 команды (рис. 3). Исключение составляет ситуация, когда команда остается одна в буфере, тогда декодируется только она одна. PC [3:2] Буфер на 4 инструкции i+3 i+2 i+1 i NOP На декодирование Рис. 3. Выбор команд из внутреннего буфера 218 Выборка происходит по битам 3 и 2 счетчика команд, так как команда имеет размер 32 бита, а счетчик адресует каждый байт. Поэтому команды всегда должны быть выровнены по границе 4 байт. Перезапись буфера происходит только при выдаче на выполнение последней команды из него. Запрос к кэш-память опережает счетчик команд на 4 (запрашивается следующая четверка команд, за той, на которую указывает счетчик команд). При запросе команд из кэш-памяти используется механизм предварительного чтения [3]. Он позволяет подгружать в кэш-память строки, которые будут использоваться в дальнейшем. Чтобы подгруженные строки не замещали строки в кэш-памяти, загрузка происходит в отдельный буфер (длиной и форматом такой же, как и строка кэш-памяти) и при выборке команд поиск происходит не только в кэш-памяти, но и в этом буфере. Запись команд в основную кэш-память происходит при повторном обращении в кэш и попадании в эту строку. Тогда по механизму замены выбирается строка для перезаписи, а дополнительная строка освобождается, и кэш может выполнять следующую команду предварительной загрузки [11]. Использование слота задержки, требуемое архитектурой, удобно в 5-ступенчатом конвейере, в разрабатываемом же 7-стадийном конвейере оно приводит к усложнению логики работы схемы переходов. При выполнении команды перехода необходимо отслеживать ситуации, когда команда из слота задержки будет размещаться в следующей запрашиваемой четверке команд. В этом случае, надо выполнять только одну (первую) команду из всех полученных. Кроме этого, на выполнение слота задержки влияют различные остановки конвейера. Возможны ситуации, когда четверка команд, содержащая слот задержки, приходит во время остановки, или когда выполнение слота задержки невозможно. При рассмотрении механизма запросов команд можно увидеть, что после получения четырех команд происходит их выполнение, и в этот момент происходит запрос следующих четырех команд из кэш-памяти. Если к моменту получения команд из кэш-памяти внутренний буфер уже пуст, то команды записываются в него, а к кэш-памяти идет следующий (3-й по порядку) запрос. Т.е. имеется возможность определить, находится ли слот задержки в следующей четверке; во время обработки запроса выполнить команду перехода; и, после получения запрошенных команд, если переход будет, выставить запрос к кэш-памяти по адресу перехода, не дожидаясь фактического выполнения слота задержки. С другой стороны, если слот задержки расположен в той же четверке, что и команда перехода, то в момент выполнения команд перехода и его слота задержки, идет запрос к кэш-памяти. После принятия решения о переходе запрошенные ранее команды не нужны, так как они не будут выполняться, а отменить запрос нельзя, поскольку он может уже обрабатываться интерфейсом шины. Однако, выданный запрос может вызвать исключение, например TLB Refill, если следующая страница не подгружена в TLB (рис. 4). Поэтому, любые исключения от запросов команд не возникают до тех пор, пока буфер команд не сформирует сигнал о выдаче на выполнении всех четырех ранее полученных команд. 0x0000 0000 0000 F000 ... ... ... ... Branch taken instr 1 0x0000 0000 0000 FFF0 instr 2 0x0000 0000 0000 FFF4 BEQ 0x0000 0000 0000 FFF8 branch delay slot 0x0000 0000 0000 FFFC 0x0000 0000 0001 0000 ... ... ... Рис. 4. Переход на границе страницы Mapped Unmapped Если при этом произошел переход, то для отмены исключений от ранее выставленного запроса предусмотрен сигнал, выставляемый буфером команд после подтверждения перехода и декодирования слота задержки (хотя сам он может еще не выполниться). На рис. 5 показана ситуация отмены ранее выданного запроса по адресу 0x0000_0000_0001_0000 при приходе сигнала, подтверждающего переход. Выполнение команд безусловного перехода (jump) происходит так же, только не формируется сигнал подтверждения перехода – он генерируется сам через один такт после выставления команды на выполнение. Для отслеживания всех возможных ситуаций при выполнении команд ветвления реализованы две машины состояний. Одна отвечает за выполнение самой команды ветвления и получения подтверждения перехода, вторая – за команду из слота задержки. Машины состояний учитывают остановки исполняющих конвейеров и переключение их состояний «привязано» к выполнению 219 команд в конвейере. Использование двух независимых машин состояний позволяет на максимально ранней стадии обновить регистр с адресом запроса команд и счетчик команд (program counter). Адрес к кэш-памяти 0x0000 0000 0000 FFF0 0x0000 0000 0001 0000 0x0000 0000 0000 FBF4 Строб запроса 4-ка инструкций Строб инструкций Инструкции в ALU Instr. 1 Инструкции в FPU BEQ Delay slot Instr. 2 Буфер пуст Подтверждение перехода Отмена предыдущего запроса TLB Refill Рис. 5. Отмена ранее выставленного запроса при подтверждении перехода Суперскалярная реализация В суперскалярной реализации одновременно могут выполняться две целочисленные команды. Для этого был добавлен второй целочисленный конвейер. При этом между двумя этими конвейерами есть различия в функциональности (рис. 6). Второй конвейер выполняет как целочисленные операции (сложение/вычитание, сдвиговые и логические операции), так и операции обмена с памятью и пересылку данных (целочисленных и вещественных). При такой реализации, выполнение вещественных операций загрузки/сохранения происходит одинаково с целочисленными, т.е. используется одна и та же схема вычисления адресов, доступа к TLB и формирования исключений. Кроме того, появляется возможность выполнять вычисления и загрузку целочисленных вещественных данных параллельно с вычислениями. Буфер команд ALU Add/Sub Shift Logic Mult/Div Move Hi/Lo Branch/Jump Pipeline 1 ALU FPU FPU Add/Sub Shift Logic Move Load/Store Move Load/Store Add/Sub Multiply Div/Sqrt Convert Pipeline 2 Pipeline 3 Рис. 6. Распределение команд по конвейерам в зависимости от типа команд Схема декодирования команд и анализа зависимостей в суперскалярной реализации усложняется. В отличие от варианта с ограниченной суперскалярностью, когда конвейер выполнения зависел только от типа команды (целочисленная или вещественная), в данном варианте необходимо проверить возможность выполнения команд с перестановкой их в разные конвейеры. Т.е. анализ идет от определения конвейера, в котором должны выполняться команды. Если одна из команд требует для своего выполнения определенного конвейера, проверяется возможность перестановки другой. Параллельно с этим проводится анализ зависимостей. Логически этот анализ во многом совпадает с анализом, проводимым в процессоре с ограниченной суперскалярностью, но, кроме этого, команды проверяются на антизависимость между собой и выполняющимися многотактовыми командами. При анализе зависимостей между целочисленными командами необходимо рассмотреть не только регистры, указанные в теле команды, но и регистры, которые будут перезаписаны по результатам её выполнения. Например, нельзя допустить параллельного выполнения команд ветвления, которая записывает текущий счетчик команд в регистр, и сложения, который записывает результат в этот же регистр. Выполниться должна только одна команда, которая является первой по порядку. Поскольку зависимости от команд загрузки отслеживаются на стадии декодирования буфером команд, то выданные в 1-й поток инструкции уже не зависят от выполнения команд во 2-м потоке, где выполняются операции обмена с памятью. Поэтому если остановки, возникающие в 220 процессе работы 2-ого конвейера, не будут влиять на работу 1-ого (целочисленного) и 3-его (вещественного) конвейера, то удастся сократить время простоя конвейеров. Однако при этом может возникнуть ситуация, когда определенная комбинация команд будет выполняться ошибочно. На рис. 7 приведены диаграммы выполнения следующей комбинации команд (показаны только стадии EXE, MEM, WB): SHIFT, LOAD1, LOAD2, ADD. Clock Выполнение Стадия MEM Стадия записи результатов Сдвиг SHIFT ADD Вычисление адреса LOAD1 LOAD2 Прощелкивание результата SHIFT Доступ в TLB ADD LOAD1 Прощелкивание результата Чтение операнда из кэш-памяти LOAD2 SHIFT ADD NOP LOAD1 NOP Остановка LOAD для доступа в joint TLB Исключение от LOAD2 Рис.7. Опоздание возникновения исключения при неблокирующемся конвейере Одновременное выполнение команд нарушается при промахе в microTLB данных обоих инструкций LOAD. В момент доступа в общий TLB команды LOAD2 и формирования сигнала исключения, команда ADD, следующая последней в приведенном фрагменте, уже закончила свое выполнение и записала результат в регистровый файл (отмечена затенением на рисунке). Для недопущения такой ситуации буфером команд проводится дополнительная проверка на возможность перестановки. Если команда, выдаваемая на выполнение во второй конвейер, идет первой по порядку в программе, она принудительно будет выдана одна. Такое решение позволяет не вводить блокировку в вычислительные конвейеры, но, в то же время, избежать таких конфликтов, как в приведенном примере. Примененные решения В разрабатываемой модели были применены следующие методы, позволяющие увеличить пропускную способность конвейера и уменьшить время его простоя: использование специальных регистров Hi/Lo для записи результатов целочисленных команд умножения и деления; загрузка одновременно четырех команд из кэш-памяти по одному запросу; упреждающее чтение команд в кэш-память по целевому адресу перехода; использование независимых машин состояний для обработки команд ветвления и её слота задержки; использование 3 независимых исполняющих конвейеров в суперскалярном варианте; неблокировка конвейеров. ЛИТЕРАТУРА John L. Hennessy, David A. Patterson. Computer Architecture – A Quantitative Approach. – Third Edition. – USA, Morgan Kaufmann Publishers, 2003. 2. John Paul Shen, Mikko H. Lipasti. Modern Processor Design. – McGraw-Hill Higher Education, 2004. 3. Harvey G. Cragon. Memory Systems and Pipeline Processors. – USA, Jones and Bartlett Publishers, 2003. 4. Alpha 21164 Microprocessor. Hardware Reference Manual. – URL: ftp.digital.com/pub/Digital/info/ semiconductor/literature/dsc-library.html. 5. MIPS64 Architecture for Programmers rev. 2.00 vol. I, II, III. – URL: http://www.mips.com. 6. MIPS R10000 Microprocessor. User’s Manual. – URL: http://www.mips.com. 7. Motorola PowerPC. MPC750 RISC Microprocessor. Family User’s Manual. URL: http://www.freescale.com. 8. The SPARC Architecture Manual. Version 8. 9. The SimpleScalar Tool Set, Version 2.0. 10. Burger D.C. Hardware Techniques to Improve the Performance of the Processor/Memory Interface // University of Wisconsin-Madison, 1998. – URL: http://citeseer.ist.psu.edu/burger98hardware.html. 11. Барских М.Е., Бычков К.С. Вариант реализации буфера команд и кэш-памяти команд. // Электроника, микро- и наноэлектроника. Сб-к научных трудов. – М.:МИФИ, 2004. – С. 191–195. 12. Рогаткин Б. Ю. Повышение эффективности преобразования виртуальных адресов памяти с помощью буфера TLB // Электроника, микро- и наноэлектроника. Сборник научных трудов. – М.:МИФИ, 2004. – С. 200–204. 1. 221