Мелкие вопросы по МК и ПЛИС.

Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Ответить
Модератор
Аватара пользователя
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля

Сообщение Аlex »

Вот это уже ближе к делу :idea:
Контактная информация:
Реклама
Вымогатель припоя
Аватара пользователя
Сообщения: 650
Зарегистрирован: Пн июн 18, 2012 12:01:04
Откуда: Челябинская область, Копейск

Сообщение zero648 »

На асме AVR это занимает 34 байта ROM, 0 RAM и 20 циклов
Реклама
Друг Кота
Сообщения: 4583
Зарегистрирован: Вс дек 05, 2010 06:10:34
Откуда: ЮВ

Сообщение HHIMERA »

Ладно... С30 PIC24...
39 байт ROM, 0 байт RAM и 13 cycles...
:)))
"Я не даю готовых решений, я заставляю думать!"(С)
Мудрый кот
Аватара пользователя
Сообщения: 1810
Зарегистрирован: Чт июн 10, 2010 08:55:35
Откуда: Сибирские Афины

Сообщение Kavka »

zero648 писал(а):На асме AVR это занимает 34 байта ROM, 0 RAM и 20 циклов
Хмм... Код покажи.
Когда уже ничего не помогает - прочтите, наконец, инструкцию.
Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII)
Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
Реклама
Эиком - электронные компоненты и радиодетали
Вымогатель припоя
Аватара пользователя
Сообщения: 650
Зарегистрирован: Пн июн 18, 2012 12:01:04
Откуда: Челябинская область, Копейск

Сообщение zero648 »

Вход - r17:r16, выход - r1:r0

Код: Выделить всё

            movw    r18, r16
            swap    r19
            andi    r19, $0f
            swap    r18
            andi    r18, $0f
            andi    r17, $0f
            andi    r16, $0f
            ldi     r20, 10
            mul     r18, r20
            add     r16, r0
            mul     r19, r20
            add     r17, r0
            ldi     r20, 100
            mul     r17, r20
            clr     r17
            add     r0, r16
            adc     r1, r17
Может, у кого еще получится ужать код
Реклама
Мудрый кот
Аватара пользователя
Сообщения: 1810
Зарегистрирован: Чт июн 10, 2010 08:55:35
Откуда: Сибирские Афины

Сообщение Kavka »

zero648 писал(а):Может, у кого еще получится ужать код
У вас без разбора из ниблов в байты: 20 байт, 13 тактов. Красиво!
С умножением здорово сэкономил! 8)
Когда уже ничего не помогает - прочтите, наконец, инструкцию.
Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII)
Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
Реклама
Друг Кота
Аватара пользователя
Сообщения: 6296
Зарегистрирован: Пн ноя 22, 2010 00:57:15
Откуда: Ukraine

Сообщение FreshMan »

в AVR, в режиме Normal при разрешении прерывания по совпадению счетчик продолжает считать дальше или сбрасывается ?
Tell Me The Truth
Друг Кота
Сообщения: 4583
Зарегистрирован: Вс дек 05, 2010 06:10:34
Откуда: ЮВ

Сообщение HHIMERA »

Kavka писал(а): 13 тактов. Красиво!
Вот только привирать... некрасиво... :)))
3*2 + 14*1 = 20 тактов... да и то... на Мега-тру-АСМ-джедайстве.. :)))
Компилятор СИ не смог одолеть архитектуру времён развитого АСМоциализма и пасущихся мамонтов... :)))

А вот это... действительно красиво... С30... GCC кстати...

Код: Выделить всё

56:                X=D*1000 + C*100 + B*10 + A;
  02A2  97B85F     mov.w [w15-6],w0         // Загружаем А, B, C и D
  02A4  97B94F     mov.w [w15-8],w2
  02A6  97BA3F     mov.w [w15-10],w4
  02A8  97BBFF     mov.w [w15-2],w7

  02AA  203E86     mov.w #0x3e8,w6         // Умножаем и складываем
  02AC  B98006     mul.ss w0,w6,w0
  02AE  200646     mov.w #0x64,w6
  02B0  B99106     mul.ss w2,w6,w2
  02B2  400002     add.w w0,w2,w0
  02B4  B9226A     mul.su w4,#10,w4
  02B6  400004     add.w w0,w4,w0
  02B8  400007     add.w w0,w7,w0

  02BA  9FBFE0     mov.w w0,[w15-4]         // Получаем результат
57:                
И ничего лишнего... как на АСМе... и каждая строчка 1 такт... :)))
"Я не даю готовых решений, я заставляю думать!"(С)
Мудрый кот
Аватара пользователя
Сообщения: 1810
Зарегистрирован: Чт июн 10, 2010 08:55:35
Откуда: Сибирские Афины

Сообщение Kavka »

HHIMERA писал(а):Вот только привирать... некрасиво... :)))
3*2 + 14*1 = 20 тактов... да и то... на Мега-тру-АСМ-джедайстве.. :)))
Это верно для полного кода приведённого zero648.
Прочитай внимательно моё сообщение!!! :evil:
Я написал про основное преобразование, т.к. исходные цифры могут храниться в разном виде.
СпойлерИзображение

Выход ассемблера (без NOP-а)

Код: Выделить всё

ATmega32A memory use summary [bytes]:
Segment   Begin    End      Code   Data   Used    Size   Use%
---------------------------------------------------------------
[.cseg] 0x000000 0x000014     20      0     20   32768   0.1%
[.dseg] 0x000060 0x000060      0      0      0    2048   0.0%
[.eseg] 0x000000 0x000000      0      0      0    1024   0.0%
Вложения
test-bcd1.png
(11.31 КБ) 382 скачивания
Когда уже ничего не помогает - прочтите, наконец, инструкцию.
Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII)
Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
Chettuser

Сообщение Chettuser »

Короче,
A - единицы;
B - десятки;
С - сотни;
В - тысячи;
X - результат.

В итоге:

Код: Выделить всё

X = A + (B<<3) + (B<<1) + (C<<6) + (C<<5) + (C<<2) + (D<<9) + (D<<8) + (D<<7) + (D<<6) + (D<<5) + (D<<3);
Для X э [0, 9999]
Башка уже не варит в математике, пойду спать, завтра додумаю.
Мудрый кот
Аватара пользователя
Сообщения: 1810
Зарегистрирован: Чт июн 10, 2010 08:55:35
Откуда: Сибирские Афины

Сообщение Kavka »

Chettuser, 82 байта, 41 такт (против 20 байт, 13 тактов у zero648).
Можно ещё на несколько команд/тактов укоротить код направив выход в исходные регистры.
Для контроллеров где нет умножения пойдёт. :)
Спойлер

Код: Выделить всё

; input - r19,r18,r17,r16
; output - r21:r20

; R = A + (B<<3) + (B<<1) 
;       + (C<<6) + (C<<5) + (C<<2)
;       + (D<<9) + (D<<8) + (D<<7) + (D<<6) + (D<<5) + (D<<3);

.def rD = r19
.def rC = r18
.def rB = r17
.def rA = r16

.def rRL = r20
.def rRH = r21

			mov		rRL,	rA		; RES = A
			mov		rRH,	rD		; RES = RES + (D << 8)
			lsl		rD				; D << 9
			add		rRH,	rD		; RES = RES + (D << 9)


			lsl		rB				; B << 1
			add		rRL,	rB		; RES = RES + (B << 1)
			lsl		rB				; B << 2
			lsl		rB				; B << 3
			add		rRL,	rB		; RES = RES + (B << 3)

.undef rB
.def rCH = r17
			clr		rCH

			lsl		rC				; C << 1
			lsl		rC				; C << 2
			add		rRL,	rC		; RES = RES + (C << 2)
			lsl		rC				; C << 3
			lsl		rC				; C << 4

			lsl		rC
			rol		rCH				; C << 5 ; (rCH:rC)

			add		rRL,	rC
			adc		rRH,	rCH		; RES = RES + (C << 5)

			lsl		rC
			rol		rCH				; C << 6

			add		rRL,	rC
			adc		rRH,	rCH		; RES = RES + (C << 6)

.undef rCH
.def rDH = r17
			clr		rDH

			lsl		rD				; D << 1
			lsl		rD				; D << 2
			lsl		rD				; D << 3
			add		rRL,	rD		; RES = RES + (C << 2)
			lsl		rD				; C << 4

			lsl		rD
			rol		rDH				; D << 5 ; (rDH:rD)

			add		rRL,	rD
			adc		rRH,	rDH		; RES = RES + (D << 5)

			lsl		rD
			rol		rDH				; D << 6 ; (rDH:rD)

			add		rRL,	rD
			adc		rRH,	rDH		; RES = RES + (D << 6)

			lsl		rD
			rol		rDH				; D << 7 ; (rDH:rD)

			add		rRL,	rD
			adc		rRH,	rDH		; RES = RES + (D << 7)
Когда уже ничего не помогает - прочтите, наконец, инструкцию.
Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII)
Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
Друг Кота
Сообщения: 4583
Зарегистрирован: Вс дек 05, 2010 06:10:34
Откуда: ЮВ

Сообщение HHIMERA »

Kavka писал(а):Chettuser, 82 байта, 41 такт (против 20 байт, 13 тактов у zero648).
Можно ещё на несколько команд/тактов укоротить код направив выход в исходные регистры.
:)))
Что в лужу... :)))
Вспомните, о чём писал вопрошающий... :)))
Chettuser писал(а):У меня не суперкомпьютер! А всего лишь скромные PIC16/18. :))
Chettuser писал(а):Опять ассемблер :(
В сети ассемблера завались, а вот на Сях...
"Я не даю готовых решений, я заставляю думать!"(С)
Chettuser

Сообщение Chettuser »

Я на работе, занят, вечером буду оптимизировать. То что выше выкладывал можно еще математически укоротить. А потом уже по железу.
Дело то в том, что X э [0, 9999] не ограничивается задача, там вплоть до X э [0, 99999999].
Друг Кота
Аватара пользователя
Сообщения: 25447
Зарегистрирован: Чт янв 10, 2008 22:01:02
Откуда: Московская область, Фрязино

Сообщение КРАМ »

Chettuser писал(а): Дело то в том, что X э [0, 9999] не ограничивается задача, там вплоть до X э [0, 99999999].
Какая разница, сколько знаков после запятой? Это лишь вопрос множителя. Все равно выводятся все значащие разряды БЕЗ ЗАПЯТОЙ, а запятая просто зажигается в нужном разряде.
Друг Кота
Сообщения: 4583
Зарегистрирован: Вс дек 05, 2010 06:10:34
Откуда: ЮВ

Сообщение HHIMERA »

Chettuser писал(а):Я на работе, занят, вечером буду оптимизировать. То что выше выкладывал можно еще математически укоротить.
Тогда берите PIC18 и HI-TECH...

Код: Выделить всё

unsigned char A,B,C,D;
unsigned int X, Y;

//X=D*1000 + C*100 + B*10 + A;

X = D*1000;
X += C*100;
X += B*10;
X += A;
выполняется за 46 cycles... что практически вровень с Мегой на СИ... :)))
На PIC18F25K20@16MHz c PLL - 2,875мкС...
"Я не даю готовых решений, я заставляю думать!"(С)
Chettuser

Сообщение Chettuser »

КРАМ писал(а):Все равно выводятся все значащие разряды БЕЗ ЗАПЯТОЙ, а запятая просто зажигается в нужном разряде.
X э [0, 99999999]
Где запятая? :) От 0 до 99999999.
Друг Кота
Аватара пользователя
Сообщения: 25447
Зарегистрирован: Чт янв 10, 2008 22:01:02
Откуда: Московская область, Фрязино

Сообщение КРАМ »

Это я слету неправильно прочел... :)
Chettuser

Сообщение Chettuser »

На текущий момент:
Спойлер

Код: Выделить всё

long int A, B, C, D, E, F, G, H, X;

int main()
{
	A = 9;
	B = 9;
	C = 9;
	D = 9;
	E = 9;
	F = 9;
	G = 9;
	H = 9;
	
	X = A;						// Прибавили еденицы
	X = X + (B<<3) + (B<<1);			// Прибавили десятки
	X = X + (C<<6) + (C<<5) + (C<<2);			// Прибавили сотни
	X = X + (D<<9) + (D<<8) + (D<<7) + (D<<6) + (D<<5) + (D<<3);	// Прибавили тысячи
	X = X + (E<<13) + (E<<10) + (E<<9) + (E<<8) + (E<<4);			// Прибавили десятки тысяч
	X = X + (F<<16) + (F<<15) + (F<<10) + (F<<9) + (F<<7) + (F<<5); 	// Прибавили сотни тысяч
	X = X + (G<<19) + (G<<18) + (G<<17) + (G<<16) + (G<<14) + (G<<9) + (G<<6); // Прибавили миллионы
	X = X + (H<<23) + (H<<20) + (H<<19) + (H<<15) + (H<<12) + (H<<10) + (H<<9) + (H<<7); // Прибавили десятки миллионов
	
    printf ("%d\n", X);

}
занимает 3758 Instruction Cycles на MCC18. Ушёл спать, оптимизирую потом.

PS: Зря я не доверял компилятору!
код

Код: Выделить всё

	X = A + (B*10) + (C*100) + (D*1000) + (E*10000) + (F*100000) + (G*1000000) + (H*10000000);
занимает всего 676 Instruction Cycles
:)))
Мудрый кот
Аватара пользователя
Сообщения: 1810
Зарегистрирован: Чт июн 10, 2010 08:55:35
Откуда: Сибирские Афины

Сообщение Kavka »

HHIMERA писал(а):Вспомните, о чём писал вопрошающий... :)))
Не на то внимание обращаешь!
Chettuser писал(а):У меня не суперкомпьютер! А всего лишь скромные PIC16/18. :))
Chettuser, если в МК есть аппаратное умножение, то такое лучше написать как есть. Перевод на сдвиги может быть только хуже, так как элементарных операций получается значительно больше. Если умножителя нет, тогда со сдвигами может быть лучше.

Могу продемонстрировать на примере AVR.
gcc version 4.3.3 (WinAVR 20100110)
Спойлер

Код: Выделить всё

unsigned int bcd4_int2(unsigned char d, unsigned char c, unsigned char b, unsigned char a) {
  return ( d*1000 + c*100 + b*10 + a );
}
С аппаратным умножением: 50 байт, 30 тактов
Без аппаратного умножения: 80 байт, 36 из них процедура умножения, 91..233 такта
Спойлер

Код: Выделить всё

unsigned int bcd4_int2(unsigned char d, unsigned char c, unsigned char b, unsigned char a) {

  return ( a + (b<<3) + (b<<1) + (c<<6) + (c<<5) + (c<<2) + (d<<9) + (d<<8) + (d<<7) + (d<<6) + (d<<5) + (d<<3) );
}
170 байт, 195 тактов (с циклами)

Слегка модифицированный вариант - попытка отучить компилятор от циклов при сдвигах.
Спойлер

Код: Выделить всё

unsigned int bcd4_int2(unsigned char d, unsigned char c, unsigned char b, unsigned char a) {

unsigned int x;
unsigned int tmp;

	x = a | (d<<8) + (d<<9);
	b = b << 1;
	x+= b;
	b = b << 1;
	b = b << 1;
	x+= b;
	c = c << 1;
	c = c << 1;  // c << 2
	x+= c;
	c = c << 1;  // c << 3
	c = c << 1;  // c << 4

	tmp = c;
	tmp = tmp << 1; // c << 5
	x+= tmp;
	tmp = tmp << 1; // c << 6
	x+= tmp;

	d = d << 1;
	d = d << 1;
	d = d << 1;  // d << 3
	x+= d;
	d = d << 1;  // d << 4
	tmp = d;
	tmp = tmp << 1; // d << 5
	x+= tmp;
	tmp = tmp << 1; // d << 6
	x+= tmp;
	tmp = tmp << 1; // d << 7
	x+= tmp;
  return ( x );
}
134 байт, 75 тактов

Варианты с аппаратным умножением и со сдвигами имеют ещё такое преимущество как фиксированное время выполнения.

Ну вот, пока я писал, Chettuser сам получил результат. :)
Когда уже ничего не помогает - прочтите, наконец, инструкцию.
Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII)
Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
Друг Кота
Сообщения: 4583
Зарегистрирован: Вс дек 05, 2010 06:10:34
Откуда: ЮВ

Сообщение HHIMERA »

Chettuser писал(а): Зря я не доверял компилятору!
код

Код: Выделить всё

	X = A + (B*10) + (C*100) + (D*1000) + (E*10000) + (F*100000) + (G*1000000) + (H*10000000);
занимает всего 676 Instruction Cycles
:)))
Вообще то... 442 Cycles на С18 и 440 Cycles на HI-TECH PICC18...
"Я не даю готовых решений, я заставляю думать!"(С)
Ответить

Вернуться в «Разные вопросы по МК»