Во многих приложениях ЦП, выполнение команд которого имеет известную временную зависимость с ожидаемыми входными стимулами, может обрабатывать задачи, для которых потребуется гораздо более быстрый ЦП, если бы эта связь была неизвестна. Например, в проекте, в котором я использовал 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; Инструкция из двух слов ; Повторите следующее, возможно, с другими операндами ; Будет продолжать добавлять значения, пока не произойдет перенос ITCC addcc r2, r2, # 0x12000000; Инструкция из двух слов, плюс дополнительное слово для itcc ITCC addcc r2, r2, # 0x12000000; Инструкция из двух слов, плюс дополнительное слово для itcc ITCC addcc r2, r2, # 0x12000000; Инструкция из двух слов, плюс дополнительное слово для itcc ITCC addcc r2, r2, # 0x12000000; Инструкция из двух слов, плюс дополнительное слово для itcc ; ... и т.д., с более условными инструкциями из двух слов sub r8, r8, # 1 bpl myloop
Во время выполнения первых шести инструкций ядро успевает извлечь шесть слов, из которых будет выполнено три, так что может быть до трех предварительно выбранных. Следующие инструкции состоят из трех слов, поэтому ядро не сможет извлечь инструкции так быстро, как они выполняются. Я ожидал бы, что некоторые из "it" -процессов будут занимать цикл, но я не знаю, как предсказать, какие из них.
Было бы хорошо, если бы ARM мог указать определенные условия, при которых синхронизация команд «it» была бы детерминированной (например, если нет состояний ожидания или конфликта кодовой шины, а предыдущие две инструкции являются 16-битными командами регистра и т. Д.) но я не видел такой спецификации.
Образец заявки
Предположим, что кто-то пытается спроектировать дочернюю плату для Atari 2600, чтобы генерировать компонентный видеовыход с разрешением 480P. 2600 имеет тактовую частоту 3,597 МГц и тактовую частоту процессора 1,19 МГц (точка часов / 3). Для компонентного видео 480P каждая строка должна выводиться дважды, что подразумевает точечный выход 7.158 МГц. Поскольку видеочип Atari (TIA) выводит один из 128 цветов, используя в качестве 3-битного сигнала яркости плюс фазовый сигнал с разрешением примерно 18 нс, было бы трудно точно определить цвет, просто взглянув на выходы. Лучшим подходом было бы перехватывать записи в регистры цвета, наблюдать записанные значения и подавать в каждый регистр значения яркости TIA, соответствующие номеру регистра.
Все это может быть сделано с помощью FPGA, но некоторые довольно быстрые устройства ARM могут быть намного дешевле, чем FPGA с достаточным объемом оперативной памяти для обработки необходимой буферизации (да, я знаю, что для томов такая вещь может быть произведена, цена не реальный фактор). Однако требование ARM следить за входящим тактовым сигналом значительно увеличит требуемую скорость процессора. Предсказуемое количество циклов может сделать вещи чище.
Относительно простой подход к проектированию заключается в том, чтобы CPLD следил за процессором и TIA и генерировал 13-битный сигнал синхронизации RGB +, а затем имел бы ARM DMA, получая 16-битные значения из одного порта и записывая их в другой с надлежащей синхронизацией. Однако было бы интересно узнать, может ли дешевый ARM сделать все. DMA может быть полезным аспектом подхода «все в одном», если его влияние на количество циклов ЦП можно предсказать (особенно если циклы DMA могут происходить в циклах, когда шина памяти в противном случае не используется), но в какой-то момент процесса ARM должен будет выполнять свои функции поиска по таблице и наблюдения за шиной. Обратите внимание, что в отличие от многих видео архитектур, в которых регистры цвета записываются во время интервалов гашения, Atari 2600 часто записывает в регистры цвета во время отображаемой части кадра,
Возможно, наилучшим подходом было бы использовать пару дискретных логических чипов для идентификации записи цвета и принудительно установить младшие биты регистров цвета в надлежащие значения, а затем использовать два канала DMA для выборки входной шины ЦП и выходных данных TIA, и третий канал DMA для генерации выходных данных. В этом случае центральный процессор сможет свободно обрабатывать все данные из обоих источников для каждой строки сканирования, выполнять необходимый перевод и буферизовать его для вывода. Единственным аспектом обязанностей адаптера, который должен был бы выполняться в «реальном времени», было бы переопределение данных, записанных в COLUxx, и об этом можно было бы позаботиться, используя два распространенных логических чипа.