Процессор имеет Неймановскую архитектуру (общее адресное пространство для исполняемого кода и данных), содержит 28 внутренних регистров, которые можно разбить на несколько функциональных групп:
– R0…R7 | extended-precision registers | регистры повышенной точности, каждый из них работает с 32-битовым целым числом или 40-битовым плавающим числом повышенной точности, которая снимает проблему накопления ошибки округления. |
– AR0…AR7 | auxiliary registers | 32-битовые вспомогательные регистры, с помощью которых организуются все методы косвенной адресации. |
– IR0, IR1 | index registers | 32-битовые индексные регистры вместе с ARx регистрами поддерживают косвенно-индексную адресацию. |
– DP | data page pointer | 32-битовый регистр указатель страницы памяти, в котором используются только 8 младших разрядов. Служит для задания старшей части адреса в случае использования прямой адресации. В машинную команду, в этом случае, помещается только 16 бит из полного 24-битового адреса. |
– BK | block size register | 32-битовый регистр, задающий размер блока для циклического типа адресации. |
– SP | system stack pointer | 32-битовый указатель стека. |
– ST | status register | регистр статуса, в котором хранятся флаги процессора, и биты управления внешними прерываниями – реакция на потенциал или спад. |
– IE | CPU/DMA interrupt enable register | 32-битовый регистр разрешения прерываний и прямого доступа. |
– IF | CPU interrupt flag register | 32-битовый регистр флагов запроса прерываний. |
– IOF | flags register | регистр ввода/вывода для сигналов XF0, XF1. |
– RC | repeat counter | 32-битовый регистр счетчика. |
– RS | repeat start register | 32-битовый регистр начала цикла. |
– RE | repeat end address register | 32-битовый регистр конца цикла. |
– PC | program counter | 32-битовый регистр счетчика команд, доступен только через команды перехода |
Типы команд
Все команды процессора имеют фиксированную длину 32 бита, их можно разбить на следующие группы:
Двухоперандные
В команде присутствуют только два операнда:
операнд1 = источник, операнд2 = приемник.
Например: ADDF *AR0,R1
сложить два числа в плавающем формате, где:
операнд1=*AR0 число по адресу, хранящемуся в регистре AR0;
операнд2 = R1 второе число из регистра R1,
результат операции помещается в R1.
Трехоперандные
В команде присутствуют три операнда:
операнд1 = источник1 , операнд2 = источник2, операнд3 = приемник результата.
Например: ADDF3 *AR0,R1,R3
сложить два числа в плавающем формате, где:
источник1=*AR0 число по адресу, хранящемуся в регистре AR0;
источник2 = R1 второе число хранится в R1,
приемник = R3 результат операции в R3.
Параллельные команды
Позволяют выполнять две команды за один машинный цикл.
Каждая из этих команд может быть или двухадресной, или трехоперандной.
Например: MPYF3 *AR0,R5,R0 || ADDF3 R7,*AR1,R2
в этом случае за один машинный цикл выполняются одновременно две команды сложения и умножения с плавающими числами.
Cпециальные команды условного/безусловного перехода
Время выполнения команд условного/безусловного перехода: Bcond, BR, DBcond, CALL, CALLcond занимает четыре машинных цикла. Для обеспечения максимального быстродействия в процессоре предусмотрены специальные “задержанные” команды перехода: BcondD, BRD, DBcondD, CALLD, CALLcondD, которые выполняются за один машинный цикл, но при этом переход осуществляется через три команды после команды перехода. Использование подобных команд требует определенной адаптации алгоритма и программы, но при этом дает ощутимый эффект.
Специальные типы адресации
– двоичноинверсная адресация (bit reversed addressing) снимает временные затраты на процедуры упорядочивания в алгоритмах быстрого преобразования Фурье, Хартли.
– циклическая адресация (circular addressing) необходима для работы с циклическими буферами, которые по достижению своего конца автоматически возвращаются в начало (отпадает необходимость программного контроля конца буфера). Позволяет ускорять вычисление корреляционных, ковариационных функций, фильтрации и т.д.
Инструкции TMS320C33 для работы с плавающей арифметикой
Все перечисленные ниже команды выполняются за один машинный цикл, при выполнении программы из внутреннего ОЗУ. При выполнении программы из внешнего ОЗУ, время выполнения программы увеличивается в 1,5 — 2 раза.
ABSF src,dst вычисляет абсолютное значение плавающего числа src, т.е. dst = |src|.
ABSF src2,dst1 || STF src3,dst2 параллельная команда, которая за один машинный цикл вычисляет модуль числа dst1 = |src2| и засылает плавающее число src3 в память dst2.
ADDF src,dst складывает два плавающих числа: dst + src –> dst.
ADDF3 src2,src1,dst складывает два плавающих числа: src2 + src1 –> dst.
ADDF3 src2,src1,dst1 || STF src3,dst2 параллельная команда, которая за один машинный цикл складывает два числа dst1 = src2 + src1 и засылает плавающее число src3 в память dst2.
CMPF src,dst сравнивает два плавающих числа dst-src, не изменяя операндов, и устанавливает флаги в регистре ST.
CMPF3 src2,src1 сравнивает два плавающих числа src1-src2, не изменяя операндов, и устанавливает флаги в регистре ST.
FIX src,dst переводит плавающее число src в целое: fix(src) –> dst.
FIX src2,dst1 || STI src3,dst2 параллельная команда, которая за один машинный цикл переводит плавающее число src в целое dst1=fix(src2) и пересылает целое число src3 в память dst2.
FLOAT src,dst переводит целое число src в плавающее число: float(src) –> dst.
FLOAT src2,dst1 || STF src3,dst2 параллельная команда, которая за один машинный цикл переводит целое число src в плавающее dst1 = float (src2) и засылает плавающее число src3 в память dst2.
LDF src,dst загружает из памяти (регистра) src плавающее число в dst: src –> dst.
LDFcond src,dst загружает из памяти (регистра) src плавающее число в dst, если выполняется условие cond: if cond is true: src –> dst.
LDF src2,dst2 || LDF src1,dst1 параллельная команда, которая за один машинный цикл выполняет две пересылки плавающих чисел: src2 –> dst2 и src1 –> dst1.
LDF src2,dst1 || STF src3,dst2 параллельная команда, которая за один машинный цикл выполняет загрузку из памяти (регистра): src2 –> dst1 и сохраняет src3 в памяти: src3 –> dst2.
MPYF src,dst перемножает два плавающих числа: dst = src * dst.
MPYF3 src2,src1,dst перемножает два плавающих числа: dst = src1 * src2.
MPYF3 srcA,srcB,dst1 || ADDF3 srcC,srcD,dst2 параллельная команда, которая за один машинный цикл выполняет команду умножения и сложения с плавающими числами: srcA * srcB –> dst1, srcC + srcD –> dst2.
MPYF3 src2,src1,dst || STF src3,dst2 параллельная команда, которая за один машинный цикл выполняет команду умножения плавающих чисел: src1 * src2 –> dst и сохранение src3 в памяти: src3 –> dst2.
MPYF3 srcA,srcB,dst1 ||SUBF3 srcC,srcD,dst2 параллельная команда, которая за один машинный цикл выполняет команду умножения и вычитания с плавающими числами: srcA * srcB –> dst1, srcD — srcC –> dst2.
NEGF src,dst арифметическое отрицание: dst = -src.
NEGF src2,dst1 || STF src3,dst2 параллельная команда, которая за один машинный цикл вычисляет обратное число: -src2 –> dst1 и сохраняет src3 в памяти: src3 –> dst2.
POPF dst переслать плавающее число со стека в регистр dst.
PUSHF dst переслать плавающее число из регистра на стек.
STF src,dst сохранение регистра src в памяти: src –> dst.
STF src2,dst1 || STF src3,dst2 параллельная команда, которая за один машинный цикл выполняет две пересылки в память: src2 –> dst1; src3 –> dst2.
SUBF src,dst вычитает два плавающих числа: dst — src –> dst.
SUBF3 src2,src1,dst вычитает два плавающих числа: src1 — src2 –> dst.
SUBF3 src1,src2,dst1 || STF src3,dst2 параллельная команда, которая за один машинный цикл выполняет вычитание двух плавающих чисел: src2 — src1 –> dst1 и сохраняет src3 в памяти: src3 –> dst2.
SUBRF src,dst вычитание dst из src с сохранением в dst: src-dst –> dst.
TMS320C33 имеет аналогичные инструкции для целочисленной арифметики.
Формат чисел с плавающей точкой
1. Числа сокращенного формата
биты машинной команды при непосредственной адресации | ||
15 14 13 12 | 11 | 10 9 8 7 6 5 4 3 2 1 0 |
Порядок числа | Знак числа | Мантисса |
2. Числа обычного формата
биты ячейки памяти | ||
31 30 29 … 25 | 24 | 23 22 21 20 … 7 6 5 4 3 2 1 0 |
Порядок числа | Знак числа | Мантисса |
3. Числа повышенной точности
биты регистра R0 — R7 | ||
39 38 37 … 34 33 | 32 | 31 30 29 28 27 … 7 6 5 4 3 2 1 0 |
Порядок числа | Знак числа | Мантисса |
Пример программы для TMS320C33
Одной из широко распространенных задач, которую часто приходится решать программистам и разработчикам электронной аппаратуры, это задача фильтрации сигналов. Для примера рассмотрим реализацию КИХ фильтра (фильтр с конечной импульсной характеристикой).
y(n)=h(0)*x(n)+h(1)*x(n-1)+…+h(N-1)*x(n-N+1)
При разработке программы важно добиться максимального использования параллельных команд и сократить время вычислений.
Ниже приведен текст программы фильтра:
AR0 | адрес буфера импульсной характеристики, указывающий на h(N-1); | |
AR1 | адрес предистории входного сигнала, указывающий на x(n-N+1); | |
RC | хранит значение N-2, порядок фильтра-2; | |
BK | хранит значение N, порядок фильтра. | |
MPYF3 | *AR0++(1),*AR1++(1)%,R0 | ;h(N-1)*x(n-N+1) –> R0 |
LDF | 0.0,R2 | ; 0e0 –> R2 инициализация |
RPTS | R C | ; начало цикла |
MPYF3 | *AR0++(1),*AR1++(1)%,R0 || ADDF3 R0,R2,R2 | ; эта команда выполняется в цикле N-1 раз ; h(N-1-i)*x(n-N+1+i)+sum |
ADDF | R0,R2,R0 | ;последнее суммирование |
RETS | ; выход из подпрограммы. |
Программа занимает шесть 32-битовых слов с временем выполнения 11 + (N-1) машинных циклов. Поскольку в данном примере используются инструкции, работающие с числами плавающего формата, нет опасности переполнений, что позволяет избежать применения дополнительных команд.
В главном цикле применена параллельная команда (MPYF3 || ADDF3), позволяющая увеличить скорость выполнения программы в два раза.