Перейти к содержанию
    

В чем причина различного написания для Cortex M4 и М0?

Библиотека 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 */

}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

пардон за оффтоп, но это уже кошмар какой-то

while(blkCnt > 0u)
  {
// тело цикла
    blkCnt--;
  }

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Почему такая конструкция считается кошмаром?

Потому что это for(;;)

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Почему такая конструкция считается кошмаром?

В основном потому, что для С-стиля совершенно естественно написать

while( blkCnt-- )

это одно из так называемых "идеоматических выражений" в языке, устойчивая, часто встречающаяся конструкция, которую все знают с первых дней изучения языка и с пониманием которой не возникает никаких проблем как раз ввиду частого использования.

Т.е. появление в коде такой конструкции с головой выдаёт недостаток опыта работы на С/С++ и то, что человек мало читал хорошего чужого кода. Это как стилистические несуразности в прозе - сразу видно что автор ни Толстого с Пушкиным, ни даже "Трёх мушкетёров" почти не читал, букварём ограничился.

Впрочем там и аналогов грамматических ошибок хватает, я в кубе уже не меньше десятка нашёл.

 

А уж уточнение что ноль беззнаковый (0u)- это просто шедевр.

Первый операнд в операции сравнения, blkCnt, объявлен как uint32_t и потому второй операнд всё равно будет приведён к unsigned типу и сравнение будет беззнаковым. Не говоря уж о том, что разница между знаковым и беззнаковым сравнением будет только когда этот несчастный blkCnt перевалит границу в 2 Гига, что на STM32 означает никогда, у него столько памяти просто нет.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

появление в коде такой конструкции с головой выдаёт недостаток опыта работы на С/С++
а может и наоборот - обнаружили что компилер лучше оптимизирует именно этот вариант.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

while( blkCnt-- )

Это будет другая конструкция, с преддекрементом индексной переменной относительно тела цикла

 

а может и наоборот - обнаружили что компилер лучше оптимизирует именно этот вариант.

Это было бы странно.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Это будет другая конструкция, с преддекрементом индексной переменной относительно тела цикла

Эта переменная ни разу не используется в теле цикла, кроме, собственно, сравнения в while() и постдекремента.

Изменено пользователем one_eight_seven

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Это будет другая конструкция, с преддекрементом индексной переменной относительно тела цикла

Разве это не постдекремент? Сначала проверили blkCnt, приняли решение идти в цикл, а потом декрементировали.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Разве это не постдекремент? Сначала проверили blkCnt, приняли решение идти в цикл, а потом декрементировали.

относительно тела цикла

 

но в данном случае без разницы, как уже выяснили.

а я бы все равно for() написал.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А уж уточнение что ноль беззнаковый (0u)- это просто шедевр.

Так делают, чтобы компилер не сыпал варнинги, типа "сравнение беззнакового и знакового".

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

но в данном случае без разницы, как уже выяснили.

а я бы все равно for() написал.

Как же, for()? Здесь не бесконечный цикл. Все работает, пока до нуля не усохнет.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Прошу разъяснить, какие отличия архитектуры 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 докопались

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

для M3 аргументами могуть быть все регистры, но из-за особенностей реализации компиляторов C, используются только четыре

Но тут почему-то 8 регистров за раз! Это не считая счётчика цикла и указателей src/dst.

Какой компилятор такое умеет, интересно?

 

 

 

P.S. словоблуды до While докопались

Вот да. А оригинальный-то вопрос интересный!

Следующий холивар "только последние дилетанты используют пробелы для отступов в коде!!!" :-(

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Пробовал компилировать для разных архитектур, ничего принципиально выигрышного от такой записи не увидел (но я программист - никакой). Может это наследие от типов q7 и q15 для использования simd инструкций? Но у М3 нет simd. Так ничего и не понял.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...