|
В чем причина различного написания для Cortex M4 и М0? |
|
|
|
Nov 18 2015, 03:04
|
Частый гость
 
Группа: Участник
Сообщений: 161
Регистрация: 29-09-10
Пользователь №: 59 816

|
Библиотека DSP STM32F4xx_DSP_StdPeriph_Lib_V1.4.0 Файл arm_add_q31.c Прошу разъяснить, какие отличия архитектуры Cortex-M3, M4 заставляют группировать по 4 операции в цикле, в отличии от одной операции в цикле для M0. Это для правильной работы конвеера? Код /** * @brief Q31 vector addition. * @param[in] *pSrcA points to the first input vector * @param[in] *pSrcB points to the second input vector * @param[out] *pDst points to the output vector * @param[in] blockSize number of samples in each vector * @return none. * * <b>Scaling and Overflow Behavior:</b> * \par * The function uses saturating arithmetic. * Results outside of the allowable Q31 range[0x80000000 0x7FFFFFFF] will be saturated. */
void arm_add_q31( q31_t * pSrcA, q31_t * pSrcB, q31_t * pDst, uint32_t blockSize) { uint32_t blkCnt; /* loop counter */
#ifndef ARM_MATH_CM0_FAMILY
/* Run the below code for Cortex-M4 and Cortex-M3 */ q31_t inA1, inA2, inA3, inA4; q31_t inB1, inB2, inB3, inB4;
/*loop Unrolling */ blkCnt = blockSize >> 2u;
/* First part of the processing with loop unrolling. Compute 4 outputs at a time. ** a second loop below computes the remaining 1 to 3 samples. */ while(blkCnt > 0u) { /* C = A + B */ /* Add and then store the results in the destination buffer. */ inA1 = *pSrcA++; inA2 = *pSrcA++; inB1 = *pSrcB++; inB2 = *pSrcB++;
inA3 = *pSrcA++; inA4 = *pSrcA++; inB3 = *pSrcB++; inB4 = *pSrcB++;
*pDst++ = __QADD(inA1, inB1); *pDst++ = __QADD(inA2, inB2); *pDst++ = __QADD(inA3, inB3); *pDst++ = __QADD(inA4, inB4);
/* Decrement the loop counter */ blkCnt--; }
/* If the blockSize is not a multiple of 4, compute any remaining output samples here. ** No loop unrolling is used. */ blkCnt = blockSize % 0x4u;
while(blkCnt > 0u) { /* C = A + B */ /* Add and then store the results in the destination buffer. */ *pDst++ = __QADD(*pSrcA++, *pSrcB++);
/* Decrement the loop counter */ blkCnt--; }
#else
/* Run the below code for Cortex-M0 */
/* Initialize blkCnt with number of samples */ blkCnt = blockSize;
while(blkCnt > 0u) { /* C = A + B */ /* Add and then store the results in the destination buffer. */ *pDst++ = (q31_t) clip_q63_to_q31((q63_t) * pSrcA++ + *pSrcB++);
/* Decrement the loop counter */ blkCnt--; }
#endif /* #ifndef ARM_MATH_CM0_FAMILY */
}
|
|
|
|
|
Nov 18 2015, 08:57
|
Профессионал
    
Группа: Свой
Сообщений: 1 719
Регистрация: 13-09-05
Из: Novosibirsk
Пользователь №: 8 528

|
Цитата(arhiv6 @ Nov 18 2015, 15:17)  Почему такая конструкция считается кошмаром? В основном потому, что для С-стиля совершенно естественно написать while( blkCnt-- ) это одно из так называемых "идеоматических выражений" в языке, устойчивая, часто встречающаяся конструкция, которую все знают с первых дней изучения языка и с пониманием которой не возникает никаких проблем как раз ввиду частого использования. Т.е. появление в коде такой конструкции с головой выдаёт недостаток опыта работы на С/С++ и то, что человек мало читал хорошего чужого кода. Это как стилистические несуразности в прозе - сразу видно что автор ни Толстого с Пушкиным, ни даже "Трёх мушкетёров" почти не читал, букварём ограничился. Впрочем там и аналогов грамматических ошибок хватает, я в кубе уже не меньше десятка нашёл. А уж уточнение что ноль беззнаковый (0u)- это просто шедевр. Первый операнд в операции сравнения, blkCnt, объявлен как uint32_t и потому второй операнд всё равно будет приведён к unsigned типу и сравнение будет беззнаковым. Не говоря уж о том, что разница между знаковым и беззнаковым сравнением будет только когда этот несчастный blkCnt перевалит границу в 2 Гига, что на STM32 означает никогда, у него столько памяти просто нет.
--------------------
Russia est omnis divisa in partes octo.
|
|
|
|
|
Nov 18 2015, 09:06
|

Беспросветный оптимист
     
Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646

|
Цитата(SSerge @ Nov 18 2015, 11:57)  while( blkCnt-- ) Это будет другая конструкция, с преддекрементом индексной переменной относительно тела цикла Цитата(ukpyr @ Nov 18 2015, 12:02)  а может и наоборот - обнаружили что компилер лучше оптимизирует именно этот вариант. Это было бы странно.
--------------------
Программирование делится на системное и бессистемное. ©Моё :) — а для кого-то БГ — это Bill Gilbert =)
|
|
|
|
|
Nov 18 2015, 09:30
|
Знающий
   
Группа: Участник
Сообщений: 916
Регистрация: 3-10-08
Из: Москва
Пользователь №: 40 664

|
Цитата Это будет другая конструкция, с преддекрементом индексной переменной относительно тела цикла Эта переменная ни разу не используется в теле цикла, кроме, собственно, сравнения в while() и постдекремента.
Сообщение отредактировал one_eight_seven - Nov 18 2015, 09:30
|
|
|
|
|
Nov 18 2015, 10:02
|

Беспросветный оптимист
     
Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646

|
Цитата(ViKo @ Nov 18 2015, 12:38)  Разве это не постдекремент? Сначала проверили blkCnt, приняли решение идти в цикл, а потом декрементировали. Цитата относительно тела цикла но в данном случае без разницы, как уже выяснили. а я бы все равно for() написал.
--------------------
Программирование делится на системное и бессистемное. ©Моё :) — а для кого-то БГ — это Bill Gilbert =)
|
|
|
|
|
Nov 18 2015, 10:10
|
Знающий
   
Группа: Участник
Сообщений: 750
Регистрация: 1-11-11
Пользователь №: 68 088

|
Цитата(SSerge @ Nov 18 2015, 11:57)  А уж уточнение что ноль беззнаковый (0u)- это просто шедевр. Так делают, чтобы компилер не сыпал варнинги, типа "сравнение беззнакового и знакового".
--------------------
"... часами я мог наблюдать, как люди работают." (М. Горький)
|
|
|
|
|
Nov 18 2015, 10:41
|

Профессионал
    
Группа: Свой
Сообщений: 1 080
Регистрация: 16-11-04
Из: СПб
Пользователь №: 1 143

|
Цитата(Михась @ Nov 18 2015, 07:04)  Прошу разъяснить, какие отличия архитектуры Cortex-M3, M4 заставляют группировать по 4 операции в цикле, в отличии от одной операции в цикле для M0. Это для правильной работы конвеера? в вашем коде идет считывание и сохранение. Это инструкции LDM и STM для M3 аргументами могуть быть все регистры, но из-за особенностей реализации компиляторов C, используются только четыре вот к примеру как идет копирование в СМ3 - сразу по 16 байт ( четыре регистра ) LDM R1!, {R3-R5, R12} SUBS R2, R2, #16 STM R0!, {R3-R5, R12} BCS.N 0x295a но в CM0 для инструкций LDM и SDM есть ограничение reglist and Rn are limited to R0-R7.P.S. словоблуды до While докопались
--------------------
Марс - единственная планета, полностью населенная роботами (около 7 штук).
|
|
|
|
|
Nov 18 2015, 12:10
|

Профессионал
    
Группа: Свой
Сообщений: 1 032
Регистрация: 13-03-08
Из: Маськва
Пользователь №: 35 877

|
Цитата(megajohn @ Nov 18 2015, 13:41)  для M3 аргументами могуть быть все регистры, но из-за особенностей реализации компиляторов C, используются только четыре Но тут почему-то 8 регистров за раз! Это не считая счётчика цикла и указателей src/dst. Какой компилятор такое умеет, интересно? Цитата(megajohn @ Nov 18 2015, 13:41)  P.S. словоблуды до While докопались Вот да. А оригинальный-то вопрос интересный! Следующий холивар "только последние дилетанты используют пробелы для отступов в коде!!!" :-(
--------------------
Тут обсуждается творческий порыв, а не соответствие каким-либо стандартам ©
|
|
|
|
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0
|
|
|