jcxz 184 15 августа, 2023 Опубликовано 15 августа, 2023 · Жалоба 32 минуты назад, Arlleex сказал: Т.е. процессор то честный, а вот особенности коммутации шин и подключенная к этим шинам память имеет свои отпечатки. Другого объяснения пока не вижу. Вы как свои тесты выполняете? Ставите бряки в начале и в конце блока кода? Или говорите выполнить до...? Я вот заметил разницу. Берём код почти как в тесте #2: LDR R7, =0E0001004h LDR R0, =10001A7Ch ADDS R2, R0, #4 ADDS R4, R0, #8 NOP NOP NOP LDR R6, [R7, #0] start: NOP NOP #if 1 LDR R1, [R0] ADDS R1, R1, #0 STR R1, [R0] LDR R3, [R2] ADDS R3, R3, #0 STR R3, [R2] LDR R5, [R4] ADDS R5, R5, #0 STR R5, [R4] #endif stop: NOP NOP LDR R1, [R7, #0] SUBS R1, R1, R6 NOP NOP NOP Выполняю его сейчас на STM32F429 от метки старт (начальное значение PC) до метки stop с помощью команды отладчика "run to cursor". Получаю время выполнения = 14 тактов (меньше на такт, чем у вас, хотя МК вроде сейчас аналогичный). Адрес я перенёс в CCM потому что у меня код сам находится в обычной ОЗУ (0x20000000) и соответственно - обращение за данными к этой же ОЗУ значительно снижает скорость выполнения. Но не суть важно. А важно другое: меняю условия теста - опять ставлю PC в ту же самую начальную точку (start), но в неё же ставлю бряк (который будет пройден сразу же, так как выполнение начнётся с него) и.... получаю время выполнения == 18 тактов! Т.е. - добавились лишние 4 такта на прохождение бряка. Может вы тоже стартуете тест с бряка, потому и получаете больше? То же самое значение я получаю и по счётчику DWT считанному самой программой: Прогон выполнения при аргументе if == 0: 5 тактов Прогон выполнения при аргументе if == 1: 19 тактов Т.е. - тестовый блок выполняется за те же 19-5=14 тактов. PS: И всё равно - на 2 такта медленнее чем на XMC4700. Видимо всё-таки как-то сказывается его 256-битная шина выборки инструкций из памяти. Хоть сейчас код и выполняется из ОЗУ. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 131 15 августа, 2023 Опубликовано 15 августа, 2023 · Жалоба Код теста у меня во Flash ; Reset handler DWT_CYCCNT EQU 0xE0001004 DWT_CONTROL EQU 0xE0001000 SCB_DEMCR EQU 0xE000EDFC Reset_Handler PROC EXPORT Reset_Handler IMPORT hwIsTargetSuit IMPORT hwInitOnSysRst IMPORT __main ; включение DWT/CYCCNT ldr r0, =SCB_DEMCR mov r1, #0x01000000 str r1, [r0] ldr r0, =DWT_CONTROL ldr r1, [r0] mov r2, #0x1 orr r1, r2 str r1, [r0] ldr r6, =DWT_CYCCNT mov r7, #0x0 ldr r0, =0x20000000 ldr r2, =0x20000004 ldr r4, =0x20000008 b loop LTORG loop str r7, [r6] ; <- это тут я зануляю CYCCNT LDR R1, [R0] ; +2 ADD R1, #0 ; +1 STR R1, [R0] ; +2 LDR R3, [R2] ; +2 ADD R3, #0 ; +1 STR R3, [R2] ; +2 LDR R5, [R4] ; +2 ADD R5, #0 ; +1 STR R5, [R4] ; +2 ldr r8, [r6] ; <- это тут я считываю CYCCNT b loop ; <- а вот здесь у меня точка останова (бряк) ENDP Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 184 15 августа, 2023 Опубликовано 15 августа, 2023 · Жалоба Добавил блок теста с примерно таким же кодом, но на 32-битных инструкциях: LDR R7, =0E0001004h LDR R0, =10001A7Ch ADDS R2, R0, #4 ADDS R4, R0, #8 NOP NOP NOP LDR R6, [R7, #0] start: NOP NOP #if 1 LDR R1, [R0] ;14 тактов ADDS R1, R1, #0 STR R1, [R0] LDR R3, [R2] ADDS R3, R3, #0 STR R3, [R2] LDR R5, [R4] ADDS R5, R5, #0 STR R5, [R4] #elif 0 LDR R8, [R0] ;17 тактов ADDS R8, R8, #0 STR R8, [R0] LDR R9, [R2] ADDS R9, R9, #0 STR R9, [R2] LDR R10, [R4] ADDS R10, R10, #0 STR R10, [R4] #endif stop: NOP NOP LDR R1, [R7, #0] SUBS R1, R1, R6 NOP NOP NOP Получил увеличение времени для него на 3 такта. Завтра, на работе, проверю сколько это выполняется на XMC4700. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 131 15 августа, 2023 Опубликовано 15 августа, 2023 · Жалоба Заметил вот что. 3 такта на LDR затрачиваются только в том случае, когда перед этой LDR стояла запись STR. Если между STR и последующим LDR поставить любую команду, то LDR начнет выполняться 2 такта. Это значит, что буфер записи очищается не сразу после завершения команды STR, а в момент выполнения следующей команды (т.е. тоже некий конвейер). И если следующая команда оказалась LDR, она должна будет дождаться реальной записи в память (очистки write buffer) в соответствии с описанием ARM. Вот было бы интересно посмотреть, что получится у XMC. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 184 15 августа, 2023 Опубликовано 15 августа, 2023 · Жалоба 1 час назад, Arlleex сказал: Заметил вот что. 3 такта на LDR затрачиваются только в том случае, когда перед этой LDR стояла запись STR. ... Вот было бы интересно посмотреть, что получится у XMC. Я же писал выше: 12 тактов. Значит там нет такого ограничения. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 131 16 августа, 2023 Опубликовано 16 августа, 2023 · Жалоба 8 часов назад, jcxz сказал: Я же писал выше: 12 тактов. Значит там нет такого ограничения. Тогда все равно есть некое непонимание, откуда получается 12 тактов. С учетом фраз из TRM на Cortex-M4 (п. Load/store timings): Цитата STR Rx,[Ry,#imm] is always one cycle. This is because the address generation is performed in the initial cycle, and the data store is performed at the same time as the next instruction is executing. If the store is to the store buffer, and the store buffer is full or not enabled, the next instruction is delayed until the store can complete. If the store is not to the store buffer, for example to the Code segment, and that transaction stalls, the impact on timing is only felt if another load or store operation is executed before completion. ... Other instructions cannot be pipelined after STR with register offset. STR can only be pipelined when it follows an LDR, but nothing can be pipelined after the store. Even a stalled STR normally only takes two cycles, because of the store buffer. В первом пункте нам четко дают понять, что приведенная форма STR занимает 1 такт, однако (внимание) этот 1 такт идет на вычисление адреса, а реальное сохранение будет в следующем такте (т.е. когда наступит выполнение следующей инструкции). Если нарисовать на бумажке множество следующих друг за другом STR, то будет видно, что "визуально" каждая из них действительно будет занимать один такт. А вот инструкция, следующая за самой последней STR в этом списке, вполне может определять, будет ли она задержана до реальной записи в память STR или нет. Второй пункт как-то расплывчато пишет об "Other instructions", не давая понимания, это для вообще любых инструкций, или только для инструкций обращения к памяти (LDR в частности). Не обратил внимание, что во втором пункте речь об STR с регистровым смещением. Мои опыты с отключением Write Buffer показывают, что если после STR идет любая инструкция, кроме загрузки из памяти, ее выполнение не будет задержано на 1 такт. А вот если после STR стоит LDR, то выполнение LDR затянется на 1 такт. Именно поэтому я видел у себя такую растактовку STR ... ; 1 такт (фаза адреса) LDR ... ; 3 такта (1 - очистка Write Buffer, 2 - стандартный CPI LDR) LDR ... ; 1 такт ... Забавно, в общем. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 184 16 августа, 2023 Опубликовано 16 августа, 2023 · Жалоба 2 часа назад, Arlleex сказал: Тогда все равно есть некое непонимание, откуда получается 12 тактов. А что Вас смущает? Вроде там всё правильно. Меня вот больше смущает почему у STM32F4 лишние такты получаются? Но скорее всего - из-за того, что операции чтения (LDR) у неё не смотрят на целевой адрес содержимого WB. 2 часа назад, Arlleex сказал: во втором пункте речь об STR с регистровым смещением. Вот именно. Не наш случай. 2 часа назад, Arlleex сказал: Мои опыты с отключением Write Buffer показывают, что если после STR идет любая инструкция, кроме загрузки из памяти, ее выполнение не будет задержано на 1 такт. А вот если после STR стоит LDR, то выполнение LDR затянется на 1 такт. Именно поэтому я видел у себя такую растактовку Подозреваю, что XMC может сравнивать целевой адрес содержимого WB и адрес слова, читаемого командой LDR. Чтобы (при необходимости) подменять чтение из реальной ОЗУ, чтением из WB. Поэтому ему и не нужна задержка на flush WB перед LDR. А в STM32F4 этого не реализовали, и потому ему нужен лишний такт на flush of WB. Почему не реализовали - вопрос. Ведь по цене (количеству вентилей в кремнии) это должно быть не дорого, а выигрыш в скорости - существенный. Потому как операции: "читаем/обрабатываем/сохраняем/читаем следующее значение" - должны быть довольно частыми в ARM-архитектуре. Но это как версия. 2 часа назад, Arlleex сказал: STR ... ; 1 такт (фаза адреса) LDR ... ; 3 такта (1 - очистка Write Buffer, 2 - стандартный CPI LDR) LDR ... ; 1 такт ... Забавно, в общем. Вот этой "1 - очистка WB" видимо в XMC и нету. имхо Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dmitrykhom 0 19 августа, 2023 Опубликовано 19 августа, 2023 (изменено) · Жалоба В 15.08.2023 в 18:39, Arlleex сказал: Только за счет большей частоты. И только. У Cortex-M7 - многостадийный декодер с несколькими исполнительными конвейерами, что дает ему возможности внеочередного исполнения потока команд. Это может быть весьма эффективно, особенно, если компилятор прошаренный и умеет нормально тасовать команды. Как это задействовать (внеочередное исполнение)? Есть ли какой пример на ассемблере? Я не спорю, что M7 эффективнее. Я просто сравнил конечный результат, используя прагматичный расчет. Мне важно, что сможет процессор успеть сделать за цикл вычислений, и сколько будет стоить спецификация PCB. Изменено 19 августа, 2023 пользователем dmitrykhom Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 131 20 августа, 2023 Опубликовано 20 августа, 2023 · Жалоба Я не сильно вдавался в подробности реализации out-of-order в M7; думаю, оно по-умолчанию включено и вообще его "выключить" нельзя. Оно будет полезно тогда, когда несколько исполнительных блоков не испытывают зависимости по данным относительно друг друга. Например, когда один выполняет сложение, а второй - умножение, при том, что операнды у них не зависят от вычислений соседнего блока. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Alexey_N 0 21 октября, 2023 Опубликовано 21 октября, 2023 · Жалоба On 8/20/2023 at 2:06 AM, dmitrykhom said: Здравствуйте. Подскажите, плз, а какому STM наиболее точно соответствует AT32F437? Я пытаюсь сконфигурировать периферию AT при помощи кубика STM (STM32F745) но там не хватает интерфейсов I2S и ещё отличия по мелочи... А есть что полностью соответствует? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dmitrykhom 0 22 декабря, 2023 Опубликовано 22 декабря, 2023 · Жалоба В 21.10.2023 в 20:47, Alexey_N сказал: Здравствуйте. Подскажите, плз, а какому STM наиболее точно соответствует AT32F437? Я пытаюсь сконфигурировать периферию AT при помощи кубика STM (STM32F745) но там не хватает интерфейсов I2S и ещё отличия по мелочи... А есть что полностью соответствует? Здравствуйте. Ничего полностью не соответствует. Нужно везде работать напильником Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться