Підрахунок циклу за допомогою сучасних процесорів (наприклад, ARM)


14

У багатьох додатках процесор, виконання інструкцій якого відомий тимчасовим зв’язком із очікуваними вхідними стимулами, може обробляти завдання, які потребувалимуть набагато швидшого процесора, якби зв'язок був невідомим. Наприклад, у проекті, в якому я використовував PSOC для створення відео, я використовував код для виведення одного байта відеоданих на кожні 16 годин процесора. Оскільки тестування того, чи готовий пристрій SPI і розгалуження, якщо не, IIRC забирає 13 годин, а завантаження і зберігання для виведення даних займе 11, не було можливості перевірити пристрій на готовність між байтами; натомість я просто домовився, щоб процесор виконував точно 16 циклів коду для кожного байта після першого (я вважаю, що я використовував реальне індексоване навантаження, фіксований навантаження та індекс). Перше записування SPI кожного рядка відбулося до початку відео, і для кожного наступного запису існувало вікно з 16 циклом, де запис може відбуватися без перекриття або заниження буфера. Цикл розгалуження породжував вікно невизначеності 13 циклу, але передбачуване виконання 16 циклів означало, що невизначеність для всіх наступних байтів відповідатиме тому самому вікні 13 циклу (що, в свою чергу, вписується у вікно 16 циклу, коли запис може бути прийнятним трапляються).

Для старих процесорів інформація про терміни інструкцій була чіткою, доступною та однозначною. Для нових ARM-файлів інформація про терміни здається набагато невиразнішою. Я розумію, що коли код виконується з флеш-пам’яті, поведінка кешування може значно ускладнити передбачення, тому я би сподівався, що будь-який перерахований цикл код повинен виконуватися з ОЗУ. Навіть при виконанні коду з оперативної пам’яті технічні характеристики здаються трохи розпливчастими. Чи використання коду, що рахується, все ще є хорошою ідеєю? Якщо так, то які найкращі методи, щоб змусити його надійно працювати? Якою мірою можна з упевненістю припустити, що постачальник чіпів не збирається мовчки ковзати в «нову вдосконалену» мікросхему, яка голить цикл виконання певних інструкцій у певних випадках?

Якщо припустити, що наступний цикл починається на межі слова, як би визначати на основі специфікацій точно, скільки часу це займе (припустимо, Cortex-M3 з пам'яттю стану нуля очікування; нічого іншого в системі не має значення для цього прикладу).

myloop:
  mov r0, r0; Короткі прості інструкції, щоб дозволити попереднє встановлення більшої кількості інструкцій
  mov r0, r0; Короткі прості інструкції, щоб дозволити попереднє встановлення більшої кількості інструкцій
  mov r0, r0; Короткі прості інструкції, щоб дозволити попереднє встановлення більшої кількості інструкцій
  mov r0, r0; Короткі прості інструкції, щоб дозволити попереднє встановлення більшої кількості інструкцій
  mov r0, r0; Короткі прості інструкції, щоб дозволити попереднє встановлення більшої кількості інструкцій
  mov r0, r0; Короткі прості інструкції, щоб дозволити попереднє встановлення більшої кількості інструкцій
  додає r2, r1, # 0x12000000; 2-слівна інструкція
  ; Повторіть наступне, можливо, з різними операндами
  ; Буде тримати додавання значень, поки не відбудеться перенос
  itcc
  addcc r2, r2, # 0x12000000; 2-слівна інструкція плюс додаткове "слово" для itcc
  itcc
  addcc r2, r2, # 0x12000000; 2-слівна інструкція плюс додаткове "слово" для itcc
  itcc
  addcc r2, r2, # 0x12000000; 2-слівна інструкція плюс додаткове "слово" для itcc
  itcc
  addcc r2, r2, # 0x12000000; 2-слівна інструкція плюс додаткове "слово" для itcc
; ... тощо, з більш умовними двословними вказівками
  під r8, r8, # 1
  bpl myloop

Під час виконання перших шести вказівок ядро ​​встигло б отримати шість слів, з яких три буде виконано, тож може бути до трьох попередньо встановлених. Наступна інструкція - це всі три слова, тому ядро ​​не може отримати інструкції так швидко, як вони виконуються. Я б очікував, що деякі інструкції "це" будуть мати цикл, але я не знаю, як передбачити, які з них.

Було б добре, якби ARM міг задати певні умови, за яких час виконання інструкцій "it" було б детермінованим (наприклад, якщо немає станів очікування або суперечки шини коду, а попередні дві інструкції - це 16-бітні інструкції реєстрації тощо). але я не бачив жодної такої специфікації.

Зразок застосування

Припустимо, хтось намагається спроектувати дочірню плату для Atari 2600 для створення компонентного відеовиходу при 480P. 2600 має піксельну тактову частоту 3,579 МГц та тактовий процесор 1,19 МГц (точковий такт / 3). Для компонентного відео 480P кожен рядок повинен виводитися двічі, маючи на увазі точковий вихід 7,158 МГц. Оскільки відео чіп Atari (TIA) виводить один із 128 кольорів, використовуючи 3-бітний сигнал луми плюс фазовий сигнал з роздільною здатністю приблизно 18ns, то було б важко точно визначити колір, просто подивившись на результати. Кращим підходом було б перехоплення записів до кольорових регістрів, дотримання записаних значень та подання кожного регістра в значення яскравості TIA, що відповідають номеру регістра.

Все це можна зробити за допомогою FPGA, але деякі досить швидкі ARM-пристрої можуть бути набагато дешевшими, ніж FPGA з достатньою оперативною пам’яттю, щоб обробляти необхідну буферизацію (так, я знаю, що для обсягів така річ може бути вироблена, вартість не буде ' t реальний фактор). Однак вимагати від ARM для перегляду вхідного тактового сигналу значно підвищить необхідну швидкість процесора. Передбачувані підрахунки циклу можуть зробити речі більш чистими.

Порівняно простий підхід до проектування полягав би в тому, щоб CPLD спостерігав за процесором і TIA і генерував 13-бітний сигнал RGB + синхронізації, а потім ARM DMA захоплював 16-бітні значення з одного порту і записував їх на інший з належною хронологією. Хоча було б цікавим дизайнерським завданням, щоб побачити, чи може дешевий ARM зробити все. DMA може бути корисним аспектом підходу «все в одному», якщо можна було б передбачити його вплив на кількість циклів процесора (особливо, якщо цикли DMA можуть відбуватися в циклах, коли шина пам'яті інакше простоює), але в якийсь момент процесу ARM повинен виконувати функції пошуку таблиці та перегляду шини. Зауважте, що на відміну від багатьох архітектур відео, де регістри кольорів записуються протягом проміжків інтервалу, Atari 2600 часто записує до кольорових регістрів під час відображеної частини кадру,

Можливо, найкращим підходом було б використання декількох чіпів дискретної логіки для ідентифікації кольорових записів та примушування нижчих бітів регістрів кольорів до відповідних значень, а потім використовувати два канали DMA для вибірки вхідних даних шини процесора та вихідних даних TIA, і третій канал DMA для генерації вихідних даних. Тоді процесор може вільно обробляти всі дані з обох джерел для кожної лінії сканування, виконувати необхідний переклад та зберігати їх для виведення. Єдиним аспектом обов'язків адаптера, який повинен був відбуватися в режимі "реального часу", було б перегляд даних, записаних на COLUxx, і це можна подбати про використання двох загальних логічних мікросхем.

Відповіді:


7

Я голосую за DMA. Це дуже гнучко в Cortex-M3 і вище - і ви можете робити всілякі божевільні речі, такі як автоматичне отримання даних з одного місця та виведення в інше із заданою швидкістю або на деяких заходах, не витрачаючи жодних циклів процесора. DMA набагато надійніше.

Але це може бути досить важко зрозуміти в деталях.

Інший варіант - це м'які сердечники на FPGA з апаратною реалізацією цих жорстких речей.


1
Мені подобається поняття DMA. Я не думаю, що в ядрі Cortex M3 немає ніякої DMA - це функція чіпів окремих виробників, і всі вони, схоже, реалізують це по-різному. Одна річ, яку я вважаю непослушною принаймні з однією реалізацією, з якою я насправді грав (STM32L152), - це те, що я не можу знайти жодного способу мати штрих-штрих при виведенні даних DMA. Також не ясно, які фактори можуть впливати на своєчасність DMA.
supercat

1
У будь-якому випадку, що стосується однієї з перших заявок, над якою я розмірковував про точний тактичний цикл, я розмістив більше інформації в оригінальному запитанні. Мені цікаво, що ти думаєш. Іншою ситуацією, коли я розмірковував над циклом, було б підривання дисплея на кольоровому РК-екрані. Дані будуть буферизовані в оперативній пам'яті з використанням 8-бітних кольорів, але дисплей потребує 16-бітних кольорів. Найшвидший спосіб, який я думав вивести дані, полягав би в тому, щоб використовувати апаратне забезпечення для генерації стробів запису, тому процесору доведеться лише виводити дані. Було б добре перевести 8-> 16 біт у маленький буфер ...
supercat

1
... а потім домовитись про те, щоб передати DMA це чи найкращий підхід?
supercat

4

Інформація про терміни доступна, але, як ви зазначали, іноді може бути невиразною. Наприклад, у Розділі 18.2 та Таблиці 18.1 Технічного довідника по роботі з Cortex-M3 є багато інформації про хронометраж (див. Тут pdf ) та уривок тут:

уривок 18.2

які дають перелік умов для максимальних термінів. Час виконання багатьох інструкцій залежить від зовнішніх факторів, деякі з яких залишають неоднозначності. Я висвітлив кожну неоднозначність, яку я виявив у наступному уривку з цього розділу:

[1] Гілки беруть один цикл для навчання, а потім завантажують конвеєр для цільової інструкції. Не взяті гілки - 1 цикл. Займаються гілки з негайним, як правило, 1 циклом перевантаження трубопроводу (всього 2 цикли). Зняті гілки з операндом реєстру зазвичай складають 2 цикли перевантаження трубопроводу (всього 3 цикли). Перезавантаження конвеєра довше [Скільки часу?] При розгалуженні на нерівні 32-бітні інструкції на додаток до доступу для уповільнення пам'яті. Підказка гілки випромінюється до шини коду, яка дозволяє повільнішій системі [Наскільки повільніше?] Попередньо завантажуватись. Це може [Чи це необов'язково?] Зменшити [на скільки?] Цільовий штраф для повільної пам'яті, але ніколи менше, ніж показано тут.

[2] Як правило, інструкції щодо зберігання вантажів займають два цикли для першого доступу та один цикл для кожного додаткового доступу. Магазини з негайними компенсаціями займають один цикл.

[3] UMULL / SMULL / UMLAL / SMLAL використовують раннє припинення залежно від розміру значень джерела [Які розміри?]. Вони перериваються (занедбані / перезапущені), з гіршим випадком затримки одного циклу. Версії MLAL займають чотири-сім циклів, а версії MULL - три-п’ять циклів . Для MLAL підписана версія на один цикл довша, ніж без підпису.

[4] ІТ-інструкції можна скласти . [Коли? Дивіться коментарі.]

[5] Терміни DIV залежать від дивіденду та дільника . [Та ж проблема, що і MUL] DIV є переривчастим (відмовився / перезапустився), з гіршим випадком затримки одного циклу. Коли дивіденд і дільник подібні [Наскільки схожі?] За розміром, ділення швидко закінчується. Мінімальний час - у випадках дільника, більших за дивіденд та дільника нуля. Дільник нуля повертає нуль (не помилка), хоча для усунення цього випадку доступна пастка налагодження. [Які діапазони були задані для MUL?]

[6] Сон - це один цикл інструкції плюс стільки циклів сну, скільки це можливо. WFE використовує лише один цикл, коли подія пройшла. WFI, як правило, більше одного циклу, якщо не трапляється переривання, яке точно відбувається під час введення WFI.

[7] ISB займає один цикл (виступає гілкою). DMB і DSB беруть один цикл, якщо дані не містяться в буфері запису або LSU. Якщо під час бар'єру відбувається переривання, воно відміняється / перезапускається.

Для всіх випадків використання вона буде складнішою, ніж "Ця інструкція - один цикл, ця інструкція - два цикли, це один цикл ...", підрахунок можливий у більш простих, повільних, старіших процесорах. У деяких випадках використання ви не зустрінете жодних неоднозначностей. Якщо у вас виникають неясності, пропоную:

  1. Зверніться до свого постачальника і запитайте, який термін виконання інструкцій у вашому випадку використання.
  2. Тест для визначення неоднозначної поведінки
  3. Повторне тестування на будь-які зміни процесора, особливо коли відбувається зміна постачальника.

Ці вимоги, ймовірно, дають відповідь на ваше запитання: "Ні, це не дуже гарна ідея, якщо тільки виникаючі труднощі не варті", - але ви вже це знали.


1
Я вважаю, що таке розпливчасте: "Перезавантаження конвеєра довше, якщо розгалуження на невідкладені 32-бітні інструкції на додаток до доступу до уповільнення пам'яті" не говорить про те, чи додано він точно один цикл, а "ІТ-інструкції можна скласти" не вказуйте, за яких умов вони будуть чи не будуть.
supercat

1
Час "ІТ" здасться особливо тривожним, оскільки це інструкція, яку часто можна використовувати в обмеженому циклі, і я впевнений, що її не завжди можна скласти. Я б припустив, що якщо кожен завжди відгалужується до початку циклу, що чутливий до часу, змушує цикл починати з межі слова, уникає будь-яких умовних навантажень або зберігання в циклі, і ніхто не вводить будь-яку інструкцію "ІТ" негайно після завантаження або оновлення магазину часові позначки "ІТ" будуть узгоджені, але специфікація не дає цього зрозуміти.
supercat

1
Моя здогадка, що ІТ, ймовірно, може (правдиво) відзначити щось на кшталт "За відсутності станів очікування або суперечки шини коду, ІТ складання гарантується, якщо (1) попередня інструкція була 16-бітною інструкцією, яка не мала доступу пам'ять або програмний лічильник; і (2) або наступна інструкція - це 16-бітна інструкція, або попередня інструкція не була ціллю "неприєднаної" гілки. Складання ІТ може відбуватися і за інших невизначених обставин ". Така специфікація дозволить писати програми з передбачуваними термінами ІТ-інструкцій, забезпечуючи, щоб код був розташований так, як зазначено.
supercat

1
Нічого собі, я визнаю, що я пройшов лише найпростіші підрахунки циклу, а не насправді боровся з застереженнями під столом. Моя оновлена ​​відповідь підкреслює деякі інші неясності.
Кевін Вермер

1
Існує багато ситуацій, коли хтось цікавиться підрахунками найгірших випадків, і справедлива кількість, коли хтось цікавиться підрахунками найкращих випадків (наприклад, якщо порт SPI може виводити один байт кожні 16 циклів, генерування кожного байту займе 14 циклів в кращому випадку, і перевірка готовності зайняла б 5 циклів, перевірка готовності кожен байт обмежив би швидкість одного разу байт кожні 19 циклів в кращому випадку; сліпо записування з двома доданими NOP дозволило б швидкості одного байта кожні 16 циклів в кращому випадку ). Випадки, коли потрібні точні терміни, не такі поширені, але вони можуть виникнути.
supercat

3

Один із способів подолати цю проблему - це використовувати пристрої з детермінованими або передбачуваними синхронізаціями, наприклад, Parallax Propeller і XMOS чіпи:

http://www.parallaxsemiconductor.com/multicoreconcept

http://www.xmos.com/

Підрахунок циклів дуже добре працює з пропелером (мова монтажу повинна використовуватися), тоді як пристрої XMOS мають дуже потужну програмну програму - XMOS Timing Analyzer, яка працює з програмами, написаними мовою програмування XC:

https://www.xmos.com/download/public/XMOS-Timing-Analyzer-Whitepaper%281%29.pdf


1
Я починаю думати, що Леон має частку в XMOS ... ;-)
Федеріко Руссо

1
Мені просто подобаються їхні фішки та люди, які там працюють. Parallax - це приємна компанія з хорошими продуктами.
Леон Геллер

1
Так, без образи. Мене просто вражає те, що всі відповіді (крім однієї), де згадується XMOS, є від вас. Немає нічого поганого в тому, щоб щось захопити.
Федеріко Руссо

@Federico, @Leon - Саме це мене трохи хвилює щодо XMOS: чому в світі є лише 1 користувач (принаймні, так це виглядає)? Якщо це так здорово, чому це не розмова про місто? Я ніколи не чув, щоб хтось про це говорив, менше використовував.
stevenvh

Спробуйте форуми XMOS: xcore.com
Leon Heller

2

Підрахунок циклів стає більш проблематичним, коли ви відходите від мікроконтролерів низького рівня та до обчислювальних процесорів загального призначення. Перші зазвичай мають чітко визначені терміни інструкцій, частково з причин, на яких ви розміщуєте сайт. Це також тому, що їх архітектура досить проста, тому час проведення інструкцій є фіксованим та відомим.

Хорошим прикладом цього є більшість мікросхем мікросхем. Серії 10, 12, 16 та 18 мають дуже добре задокументовані та передбачувані терміни інструкцій. Це може бути корисною функцією у вигляді малих програм управління, для яких призначені ці мікросхеми.

Коли ви відходите від наднизької вартості, і дизайнер може, таким чином, витратити трохи більше мікросхем, щоб отримати більш високу швидкість від більш екзотичної архітектури, ви також уникнете передбачуваності. Подивіться на сучасні варіанти x86 як на крайні приклади цього. Існує кілька рівнів кеш-пам'яті, вітуалізація пам’яті, пошук даних, конвеєр та інше, що робить підрахунок циклів інструкцій майже неможливим. У цій програмі це не має значення, оскільки клієнт зацікавлений у високій швидкості, а не передбачуваності термінів інструкцій.

Цей ефект можна навіть побачити на роботі у вищих моделях Microchip. 24-бітове ядро ​​(серія 24, 30 та 33) має значною мірою передбачувані терміни інструкцій, за винятком кількох винятків, коли є регістри змісту шини. Наприклад, у деяких випадках машина вставляє стійло, коли наступна інструкція використовує регістр з деякими режимами непрямої адреси, значення яких було змінено в попередній інструкції. Цей тип стійла незвичайний на dsPIC, і більшу частину часу ви можете його ігнорувати, але він показує, як ці речі повзуть завдяки дизайнерам, які намагаються надати вам більш швидкий і здатний процесор.

Отже, основна відповідь - це частина компромісу, коли ви вибрали процесор. Для невеликих програм управління ви можете вибрати щось невелике, дешеве, з низькою потужністю та з передбачуваними термінами інструкцій. Оскільки ви вимагаєте більшої потужності для обробки, архітектура змінюється так, що вам доведеться відмовитися від передбачуваних термінів інструкцій. На щастя, це менше питання, коли ви потрапляєте до більш обчислювальних і загальноприйнятих додатків, тому я думаю, що компроміси працюють досить добре.


Я погоджуюсь, що загалом додатки, що більш інтенсивно обчислюються, стають менш чутливими до мікроскопічного синхронізації, але є деякі сценарії, коли, можливо, потрібно трохи більше омфи обробки, ніж PIC-18, але також потрібна передбачуваність. Мені цікаво, якою мірою я повинен прагнути вивчати такі речі, як 16-бітна архітектура PIC, або в якій мірі я вважаю, що ARM, ймовірно, буде адекватним.
supercat

0

Так, ви все ще можете це зробити, навіть на ARM. Найбільша проблема з цим в ARM полягає в тому, що ARM продає ядра не чіпи, і основний термін відомий, але те, що постачальник чіпів обертає навколо нього, варіюється від постачальника до постачальника, а іноді і від сімейства чіпів до іншого всередині постачальника. Таким чином, певний чіп від конкретного постачальника може бути досить детермінованим (якщо ви, наприклад, не використовуєте кеші), але стає важче для порту. У роботі з 5 годин та 11 годин із використанням таймерів є проблематичним, оскільки кількість інструкцій, необхідних для вибірки таймера та з'ясування, чи закінчився термін очікування. Зі звуків вашого минулого досвіду програмування, я готовий зробити ставку, що ви, мабуть, налагоджуєтесь за допомогою осцилографа, як і я, тому ви можете спробувати щільну петлю на мікросхемі за тактовою частотою, подивитися на spi або i2c або будь-яку форму сигналу, додайте або видалити соски, змінити кількість разів через цикл і в основному настроїти. Як і на будь-якій платформі, не використання переривань значно допомагає детермінованому характеру виконання інструкцій.

Ні, це не так просто, як PIC, але все ж цілком здійсненно, якщо затримка / час наближається до тактової частоти процесора. Кілька постачальників на основі ARM дозволяють вам помножити тактову частоту і скажіть 60 МГц від 8 МГц, тому якщо вам потрібен інтерфейс 2 МГц замість того, щоб робити що-небудь кожні 4 інструкції, ви можете збільшити годинник (якщо у вас є бюджет живлення), а потім скористайтеся таймером і дайте собі багато годин, щоб робити і інші речі.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.