[an error occurred while processing this directive]
|
Это означает, что не во всех случаях можно сразу следующей командой использовать данные, являющиеся результатом выполнения предыдущей. То есть после определенных команд необходимо ставить delay-слоты, как при команде перехода. Например любая команда загрузки из памяти требует 4 слота, умножение - 1 слот, команды перехода - 5 слотов. Плавучка кроме того бывает с functional unit latency. - это объясню ниже.
Вот пример кода:
Под этим:
[ до 8-ми инструкций]
подразумевается, что все они параллельны, то есть это есть один execute packet и выполняется/запускаются в один такт.
LDW .D1 *A10++, A1 ; старт загрузки из *A10++ в A1
[|| до 7-ми инструкций на других юнитах, не D1]
LDW .D1 *A10++, A1 ; старт загрузки из *A10++ в A1
[|| до 7-ми инструкций на других юнитах, не D1]
[ до 8-ми инструкций] ; a1 имеет еще старые значения
[ до 8-ми инструкций] ; и с ними тут пока можно продолжать
[ до 8-ми инструкций] ; работу
[ до 8-ми инструкций] ; только тут в A1 пришел результат LDW
[ до 8-ми инструкций] ; а тут в A1 пришел результат след. LDW
B .S2 label ; команда перехода
[|| до 7-ми инструкций на других юнитах, не S2]
[ до 8-ми инструкций]
[ до 8-ми инструкций]
[ до 8-ми инструкций]
[ до 8-ми инструкций]
[ до 8-ми инструкций] ; только после этого execute packet'а
; произойдет переход.
То есть на примере LDW - требуется 5 тактов для ее выполнения (4 delay слота), но functional unit latency =1, что означает, что команды LD* (на одном и том-же юните) можно ставить одну за одной в тексте. То есть каждый такт процессора на любом из D-юнитов (или на обоих) запускать по команде LD*.
Плавучка-же (IEEE, только часть double precision и умножение интеджер 32вит*32бит=>64бит) обладает особенностью иметь functional unit latency отличную от 1. Например MPYDP - умножение двух IEEE dbl. prec. выполняется 10 циклов и имеет latency 4. Это значит, что после пуска операции MPYDP на юните например M1 следующие три такта нельзя на этом-же юните ничего делать. Пример:
Пускаем умножение [64-бит IEEE dbl]*[64-бит IEEE dbl]
и одновременно загрузку из *B11 в B1
и одновременно сложение B3 с B4 IEEE single prec.
и одновременно сложение конст. 1234 с рег. A3 интеджер
MPYDP .M1 A1:A0, A3:A2, A5:A4
|| LDW .D2 *B11, B1
|| ADDSP .L1 B3,B4
|| ADDK .S1 1234,A3
[|| до 4-х инструкций на оставшихся юнитах (D1, L2, M2, S2)]
[до 7-ми инструкций на юнитах кроме M1] ; к A3 уже прибавилось.
[до 7-ми инструкций на юнитах кроме M1]
[до 7-ми инструкций на юнитах кроме M1]
[ до 8-ми инструкций] ; тут в B4 уже попал результат ADDSP
[ до 8-ми инструкций] ; тут в B1 уже попал результат LDW
[ до 8-ми инструкций]
[ до 8-ми инструкций]
[ до 8-ми инструкций]
[ до 8-ми инструкций]
[ до 8-ми инструкций] ; тут A5:A4 содержит результат MPYDP
То бишь ADDK не имеет delay-слотов (выполняется 1 такт), LDW и ADDSP требуют delay-слотов (3 и 4 соотв.), но не имеют func. unit latency, а MPYDP имеет и то и другое (9 слотов и 4 latency).
Под scheduling подразумевается именно распределение операций по юнитам так, что бы каждый такт выполнялось (или запускалось) наибольшее число операций и наименьшее число юнитов простаивало.
Например из-за шеститактовости команды перехода минимальная длительность цикла есть 6 execute packet'ов. То есть 6...48 команд. Правильный scheduling этого цикла означает, что за одну итерацию выполняется максимально возможное количество реальных итераций цикла. Компилер C умудряется делать от 1:2 до 1:6.
Не знаю, насколько понятно объяснил. Если где ошибся, то подправьте....
Ну если интересны подробности, кто сколько и как выполняется, то читайте SPRU189F
E-mail: info@telesys.ru