Cтраница 2
![]() |
Работа суперскалярного процессора с изменением последовательности запуска и завершения команд. [16] |
Несмотря на то, что команда 4 простаивает, мы можем декодировать и запустить команду 5, поскольку она не создает конфликтной ситуации ни с одной из выполняющихся программ. Однако пропуск команд порождает новую проблему. В результате нам придется расширить счетчик обращений, чтобы следить за записями, которые совершают пропущенные команды. Правило для запуска команд следует расширить, с тем чтобы предотвратить запуск команды, операнд которой должен быть записан той предшествующей командой, что шла до нее, но была пропущена. [17]
Такую структуру можно будет запросто отладить, хотя она, по-видимому, окажется мучительно неэффективна. В каждом гнезде словаря будут четыре поля: цепочка литер, частота гнезда во время построения словаря, кодировка, присвоенная этой цепочке, и счетчик обращений к ней при сжатии текста. Первое полноценное гнездо всегда имеет номер 0, а последнее - DICTIONARY. Максимальный размер словаря задает макро DICTIONARY. При поиске требуется лишь полный просмотр всех гнезд словаря; новые гнезда могут добавляться в конец таблицы. При исключении низкочастотных гнезд на их место переписываются высокочастотные гнезда; читателю надлежит убедиться самому, что при работе цикла, описанного в строках 261 - 270, информация не теряется. Обратите внимание, что вычисление параметров, влияющих на степень сжатия, разнесено по самостоятельным подпрограммам, приведенным в строках 154 - 193, что позволяет с легкостью их отыскать и заменить. Мы предпочли здесь удобство в ущерб эффективности: в окончательной рабочей версии желательно исключить подпрограммы вычисления параметров, а требуемые функции переписать прямо в тех местах, где они должны использоваться. [18]
В связи со спекулятивным выполнением команд возникают некоторые интересные проблемы. Например, очень важно, чтобы ни одна из спекулятивных команд не имела окончательного результата, который нельзя отменить, поскольку позднее может оказаться, что эти команды не нужно было выполнять. Обратимся к листингу 4.6 и рис. 4.30. Очень удобно производить сложение, как только появляется значение k ( даже до условного оператора i f), но нежелательно сохранять результаты в памяти. Чтобы предотвратить перезапись регистров до того, как стало известно, полезны ли полученные результаты, нужно переименовать ( подменить) все выходные регистры, которые используются спекулятивной командой. Как вы можете себе представить, счетчик обращений для отслеживания всего этого очень сложен, но при наличии соответствующего аппаратного обеспечения его вполне можно сделать. [19]
Перейдем к блоку отправки / выполнения, который изображен на рис. 4.33. Этот блок устанавливает очередность и выполняет микрооперации, разрешает взаимозависимости и конфликты ресурсов. Такую скорость нельзя поддерживать, поскольку она превышает способности работы блока возврата. Микрооперации могут запускаться не по порядку, но блок возврата должен завершать их выполнение по порядку. Чтобы следить за микрооперациями, регистрами и функциональными блоками, требуется сложный счетчик обращений. Когда операция готова Для выполнения, она может начаться, даже если другие операции, которые поступили в буфер ROB раньше нее, еще не готовы. Если несколько микроопераций пригодны для выполнения одним и тем же функциональным блоком, с помощью сложного алгоритма выбирается важнейшая из них, и именно она и запускается следующей. Например, выполнение перехода гораздо важнее, чем выполнение арифметического действия, поскольку первый из них влияет на ход программы. [20]