Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Умножение 2байтовых чисел
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
skopus
Как можно использовать аппаратный умножитель, чтобы ускорить процедуру умножения чисел типа 16 x 9 и 16 x 8?

В первом случае совсем трудно. Для того чтоб сохранить необходимую точность, приходится использовать 9 битное значение в таком вот, например, формате:

01:C5 = 1.769227
00:B9 = 0.721208
81:30 = -1.188309
80:83 = -0.511272

Я так понимаю, что команда FMULS мне не подходит. В книге Евстифеева сказано, что формат 1.7 (страший разряд - целая часть, младший - дробная) Кстати где тогда хранится знак? и чем тогда отличается от FMUL ?

Поскольку я переделываю старую программу написанную для другого процессора, где не было аппаратного умножителя, то в принципе можно все сделать по аналогии. Но мы очень расчитывали на то, что можно будет выполнить умножение не за 85 тактов, а всего за 2. Так что вопрос быстродействия стоит ребром.

Может у кого-нибудь есть идеи по этому поводу?
Буду очень благодарен
KRS
По поводу знака -
для FMUL без знака исходные числа от 0 до <2
а если со знаком то больше -1 но меньше 1 т.е целой части нет вообще
а так как и обычные отрицательные дополнение до двух


для того что бы умножить числа больше 8 бит
проще всего написать на бумажке в виде байтов птом записать на асме
примерно так
(a+b<<8)*c= a*c + (b*c)<<8 -- 2 умножения одно сложение (16 битное)



У атмела есть апп нот
UsingtheAVRHardwareMultiplier
http://www.atmel.com/dyn/resources/prod_do...nts/DOC1631.PDF
Rash
Смотри команды: MULS ? MULSU и т.д. в инструкциях по AVR, там на асме, Вот пример оттуда
Код
Example:
;******************************************************************************
;* DESCRIPTION
;*Signed multiply of two 16-bit numbers with 32-bit result.
;* USAGE
;*r19:r18:r17:r16 = r23:r22 * r21:r20
;******************************************************************************
muls16x16_32:
clrr2
mulsr23, r21; (signed)ah * (signed)bh
movwr19:r18, r1:r0
mulr22, r20; al * bl
movwr17:r16, r1:r0
mulsur23, r20; (signed)ah * bl
sbcr19, r2
addr17, r0
adcr18, r1
adcr19, r2
mulsur21, r22; (signed)bh * al
sbcr19, r2
addr17, r0
adcr18, r1
adcr19, r2
ret

см. файл
skopus
Спасибо огромное! Очень ценный PDF!
m16
Добавлю , у атмела есть апнота
Rash
Если не вкурсе зайди сюда, тут много чё на русском найдётся
http://www.efind.ru/ad/adframe.php?n=a40f2...3&target=_blank
skopus
в апноте в разделе про умножение 16 на 16 с 16 битным результатом есть следующаая фраза.
when doing integer multiplication in C language, this is how it is done. Значит ли это, что, к примеру, в IAR C обычнфй оператор умножения работает именно так, как предлагается в аппноте?

Цитата(Rash @ Nov 23 2005, 17:22) *
Если не вкурсе зайди сюда, тут много чё на русском найдётся
http://www.efind.ru/ad/adframe.php?n=a40f2...3&target=_blank


по этой ссылке только реклама, заблокированная аутпостом...
vet
Цитата(skopus @ Nov 23 2005, 17:28) *
в апноте в разделе про умножение 16 на 16 с 16 битным результатом есть следующаая фраза.
when doing integer multiplication in C language, this is how it is done. Значит ли это, что, к примеру, в IAR C обычнфй оператор умножения работает именно так, как предлагается в аппноте?


Только в целочисленной арифметике. Но можно задействовать умножитель и для умножения чисел с плавающей точкой, включив в проект библиотеку math_mega.s90 (поищите в Сети).
AVRGCC последних сборок (октябрь-ноябрь '05) использует аппаратный умножитель для чисел с плавающей точкой, раньше этого не было.
Rash
Цитата(skopus @ Nov 23 2005, 18:28) *
в апноте в разделе про умножение 16 на 16 с 16 битным результатом есть следующаая фраза.
when doing integer multiplication in C language, this is how it is done. Значит ли это, что, к примеру, в IAR C обычнфй оператор умножения работает именно так, как предлагается в аппноте?

Цитата(Rash @ Nov 23 2005, 17:22) *

Если не вкурсе зайди сюда, тут много чё на русском найдётся
http://www.efind.ru/ad/adframe.php?n=a40f2...3&target=_blank


по этой ссылке только реклама, заблокированная аутпостом...


Извините сюда:
http://www.gaw.ru/html.cgi/txt/doc/micros/avr/index.htm
KRS
Цитата(skopus @ Nov 23 2005, 17:28) *
в апноте в разделе про умножение 16 на 16 с 16 битным результатом есть следующаая фраза.
when doing integer multiplication in C language, this is how it is done. Значит ли это, что, к примеру, в IAR C обычнфй оператор умножения работает именно так, как предлагается в аппноте?

Цитата(Rash @ Nov 23 2005, 17:22) *

Если не вкурсе зайди сюда, тут много чё на русском найдётся
http://www.efind.ru/ad/adframe.php?n=a40f2...3&target=_blank


по этой ссылке только реклама, заблокированная аутпостом...


Да код в IAR получается примерно такой же как в аппноте так что можно смело пользоваться им.
mse
Мож я чего не понял? А в чём проблема? Обычное умножение с фикс точкой. Умнож обычным многобайтным способом и учти, что в результате за точкой будет q1+q2 битов. Всё. Хош signed, хош unsigned. В аппноте заготовки есть. Расширь их на нужное кол-во байт.
skopus
блин, никогда этим не занимался sad.gif
А это нужно обязательно реализовывать на ассемлере? или достаточно использовать в iar c данные типа short (2 байтные) а потом форматировать результат?
Виктория
Цитата
Умнож обычным многобайтным способом и учти, что в результате за точкой будет q1+q2 битов.

В общем случае для формата целочисленного формата с дробной точкой и перед точкой биты расширяются n1+n2. Т.е. результат умножения числа в формате M.N на число в формате P.Q имеет формат (M+P).(N+Q). ((1.8) на (1.8) -> (2.16)). На Си конечно можно, только все это нужно учитывать и сдвигать результат (если необходимо).
skopus
так и не получилось у меня реализовать это в IAR C. А сильно ли тормозит атмега при использовании float?

Или может кто не поленится и напишет примерчик как умножать числа в формате 2.14 в яре с использованием int ?

то есть - знак|целаячасть|.|дробная часть
mse
Цитата
Или может кто не поленится и напишет примерчик как умножать числа в формате 2.14 в яре с


о дела... а аппноту стандартную, таки никак? Ниасилил?
Код
;r19...r16 = r23:r22 * r21:r20

    clr       r2
    muls       r23, r21    ; (signed)ah * (signed)bh
    movw       r18, r0
    mul       r22, r20    ; al * bl
    movw       r16,r0
    mulsu       r23, r20    ; (signed)ah * bl
    sbc       r19, r2
    add       r17, r0
    adc       r18, r1
    adc       r19, r2
    mulsu       r21, r22    ; (signed)bh * al
    sbc       r19, r2
    add       r17, r0
    adc       r18, r1
    adc       r19, r2

это обычное знаковое умножение 16х16=32. Достаточно просто переделывается для произвольного кол-ва байт. Если у тебя операнды имеюцца в виду как s_d1.q1 и s_d2.q2, то результат умножения будет s_(d1+d2).(q1+q2)
где s, q1,q2 и d1,d2 - знак, кол-во бит после запятой и до запятой, соотвецтвенно. "." - запятая
В Ц это реализуется аналогично. Числа объявляются как целые знаковые нужного размера, только ты вручную манипулируешь фиксированной точкой, т.е помнишь, где она располагается после умножения. Фсё.
Что касаецца плывучки, то военного в ней ничего нет. Умножение, практицки то-же самое по времени, тока чуть длиннее, на копеечку. Арифметика - гораздо длиннее за счёт денормализации-нормализации. Ну и проверки разные на стандартные ситуаццыи.
skopus
а как использовать ассемблерную функцию в Си. Я уже несколько раз прочитал апнот, но так и не добился ничего.

файл ассемблерной функции fmuls16x16_32.s90 выглядит так:

#include <iom128.h>

NAME fmuls16x16_32
PUBLIC fmuls16x16_32

RSEG CODE
fmuls16x16_32:
movw r17:r16, r23:r22 ;перенести из R16,R17
clr r2
fmuls r23, r21 ; ( (signed)ah * (signed)bh ) << 1
movw r19:r18, r1:r0
fmul r22, r20 ; ( al * bl ) << 1
adc r18, r2
movw r17:r16, r1:r0
fmulsu r23, r20 ; ( (signed)ah * bl ) << 1
sbc r19, r2
add r17, r0
adc r18, r1
adc r19, r2
fmulsu r21, r22 ; ( (signed)bh * al ) << 1
sbc r19, r2
add r17, r0
adc r18, r1
adc r19, r2
ret
END

в основном файле программы я объявляю ее как

extern long fmuls16x16_32(int A, int С);


А в ответ получаю ошибку от компилятора:

Error[e46]: Undefined external "fmuls16x16_32(int, int)" referred in usercode ( C:\IAR C\projects\Debug\Obj\usercode.r90 )
m16
skopus
Зачем это нужно? ИАР использует аппаратный умножитель при генерации кода
skopus
результат его умножения я вообще не могу интерпретировать. Уж лучше на асме. по крайней мере так мне понятно, что происходит.

А проблема решилась объявлением

extern "C"
{
long fmuls16x16_32(int A, int С);
}
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.