ВходНаше всё Теги codebook 无线电组件 Поиск Опросы Закон Пятница
26 апреля
264295
Evgeny_CD, Архитектор (28.07.2011 19:51 - 20:53, просмотров: 27185)
Зачитал я тут доку на свежий Microblaze (Xilinx) и протащился! (Я не знаю, есть это в NIOS-II (Altera) или нет – читал в описываемой части токо доку по Microblaze) [upd: добавил Spartan-3E для сравнения]. С того самого счастливого момента, как я немного стал понимать, работу Осей, меня всегда бесило то, насколько распространенные процы и Оси ортогональны друг другу. Основное:
  • Скорость переключения контекста. Просто выгружать регистры в память – не быстро. Делать теневые банки – недешево по ресурсами кристалла и плохо масштабируется (вдруг у меня будет не 16 задач, как в SH-2A теневых банков, а 18?).
  • Работа с системными структурами. Разделение доступа, работа с большими объектами – как же все это не быстро в реале работает…
  • Грамотная работа с DMA. Чтобы при мелких пакетах скорость не терялась. А то пока DMA запрограммируешь, пока проверишь – а оно завершило или нет – процом проще переслать…
  • Отсутствие гибкости. Нельзя все задачи причесывать под одну гребенку! Я бы выделил 4 класса:
  • * Fast interrupt – все для процедуры лежит в SRAM на тактовой процессора. * System routine – как и предыдущее, но в силу большего объема кода и данных они только частично хранятся в локальной памяти. * Schedulable routine. В процессе работы системы хороший шедулер (пусть он для простоты работает параллельно основному процу) заранее сможет предсказать порядок вызова «больших задач». Либо ему можно подсказать из текущей задачи. Т.е. типа прерывание случится когда угодно, но мы его и обработаем быстро, а вот вызов следующей тяжелой задачи можно понять на основе данных от объектов Оси и какой-то информации от текущей задачи. Тогда можно заранее дать команду продвинутому менеджеру памяти (очень продвинутый DMA) –типа загрузи мне стек этой задачи вот сюда, в быстрое статическое локальное ОЗУ, и кусочек программного кода начиная от точки, с которой мы прервали задачу, вот в этот кеш лайн (или эти кеш лайны). И когда все готово – тут мы задачи и переключаем с минимальными задержками. Пусть не все данные и код этой задачи мы загоняем в локальное ОЗУ, но если грамотно загрузить их в кеш – старт «новой» задачи будет без ожидания. * Asynchronus user space – а вот это POSIX. Типа все красиво, стандартно, но очень медленно. Ну чтобы пЫтоны и лУа всякие запускать в полном *NIX окружении. Все живет в SDRAM и работает крайне неторопливо. Время меряется миллисекундами и десятками миллисекунд. DMA вообще должно быть совершенно другим. Это не просто набор регистров, это простенький процессор со специализированной системой команд. Типа ждать вот этого сигнала, брать отсюда, класть сюда, так-то модифицировать указатели, так то модифицировать данные, выставлять такие-то сигналы. И отдавать ему команды я должен как сопроцессору, в основном потоке команд, без задержек. Прочитав доку, я понял, что я не одинок в своих бредовых фантазиях! Что меня поразило: * Специальный бит атомизации для многих команд Microblaze. * Легкость (на бумаге) создания собственного сопроцессора. Мои мечты обретают реальность. Вот как я себе это мыслю. IP тек. Пришел пакет. И попал в спецобработчик. Он подсчитал CRC IP, выделил в пакете дескрипторную часть, преобразовал ее в C структуру, чтобы процу было очень удобно работать с ней, положил в некую быструю память, данные загнал в медленную память, положив указатель и длину в дексриптор, проинкрементировал число необработанных пакетов и суммарный объем данных, и уснул. Вот юзеровское приложение. Которое записало в буфер сокета. Т.е. оно запросило менеджер памяти. Он дал ему нужный кусочек памяти. Юзер заспамил кусочек, дал сокету указатель и длину. Аналогично проикрементировался счетчик необработанных данных сокета. Шедулер постоянно мониторит – что делать далее? Ага, вот необработанные данные по входным пакетам превысили лимит, вот данные по буферу сокета – надо вызвать IP стек. Но вначале мы дадим команду подкачать в локальное адресное пространство дескрипторную часть данных стека, и когда они закачаются, переключим задачи. Никто никого ждать не будет, все на мази. Ага, стек отработал и решил – вот этот кусок данных (! Не обрабатывая сами данные !) надо засунуть в буфер сокета, вот тогда-то обработать такой-то код (истечение таймеров) и т.д. Далее у нас есть менеджер композитных объектов – еще один программируемый сопроцессор. Который суть обрабатывает связный список кусочков в памяти. И у нас есть команды работы с этими композитными объектами, как с файлами – установить указатель, считать данные и т.д. Стек выдает команду менеджеру – включить такой-то кусок в буфер сокета. И усе! Теперь по работе с памятью. SDRAM хорошо работает пакетами! А с небольшой локальной памятью в FPGA поступаем так. Распределяем все адресное пространство между задачами. Где у них код, где данные. И коммутируем старшие биты адреса каждого 2 кб блока :) Т.е. вот сейчас этот блок – данные задачи А по такому-то адресу. Шедулер запускает системную задачу С. Пока она работает, блок данных задачи А загоняется в SDRAM, в тот же блок записывает данные задачи Б, коммутирует его на адресное пространство Б, и когда С отработает, запускает задачу Б на готовом :) Рядом с системным таймером живет двухслойное бинарное дерево поиска. С аппаратной поддержкой. Там записано, в какие моменты какие системные события наступят, и все запрос от задач «ждать 20 мс» пропускаются через то же дерево. Двухслойность означает, что «быстрые» события записаны в локальной памяти, а до которых далеко –живут в SDRAM. По мере продвижения времени и освобождение локальной памяти подкачиваем из SDRAM. Суть всей этой суеты примерно такова. Я всегда поражался многомегабайтным кешам современных процессоров. Ну нахуа процу 2Мбайта кеша, он же столько данных за раз необработает! Это плата за отсутствие планирования работы с памятью силами программиста. И отсутствие сопроцессоров для работы с памятью. Теперь разберемся «скоко стоит». 40 нм Spartan-6 в корпусе BGA 256. Первая цифра – 40, 2-я коммерческие. digikey.com 16k LE. 32 блока BRAM 2k, 32 DSP48A1 Slices XC6SLX16-2FTG256I $27.93 XC6SLX16-2FTG256C $24.27 25k LE 52 блока BRAM 2k, 38 DSP48A1 Slices XC6SLX25-2FTG256I $39.37 XC6SLX25-2FTG256C $34.25 25k LE в больших корпусах 484 1 мм (266 IO) XC6SLX25-N3FGG484C - 45.29 (нет на складе) XC6SLX25-2FGG484I - 52.07 Навороченные донельзя 150k LE 268 блока BRAM 2k, 180 DSP48A1 Slices в тех же больших корпусах 484 1 мм (338 IO). Дорого, но для макетно-транировочных вариантов самое то. Зато 0.5 мБайта статического ОЗУ на кристалле :) XC6SLX150-2FGG484C - 158.75 XC6SLX150-2FGG484I - 182.50 (нет на складе) Спартан 3 (предыдущее поколение) 19.5 k LE. 28 блоков памяти 2к. 28 умножителей 16 х 16. Разница в цене индустриальных очень мала, но камень сильно проигрывает по цене и ресурсами 25-ке строкой выше. XC3S1200E-4FTG256I - 43.74 XC3S1200E-4FTG256C - 42.16 CYCLONE® IV E 15k LE от Altera. 56 умножителей 16 х 16, 1кб блоков тоже что-то типа 56. EP4CE15F17C8N 28.93 - нет в продаже. Коммерческий. EP4CE15F17C7N 36.16 Коммерческий. EP4CE15F17I8LN 43.39 Индустриальный. На коммерческие цены у Altera похожи, а вот индустриальные у нее традиционно задраны. Навороченный Microblaze с отладкой, кешами, контроллером памяти и пр. «весит» <4k LE. Навороченные контроллер SDRAM ~2…3 k LE. (это если не использовать встроенный hard контроллер DDR) Так что в 16 k LE влезет немало чего. В качестве бонуса есть PicoBlaze, который занимает что-то типа 200 LE и половину 2к блока памяти под код. Так что сопроцессоров можно наплодить немеренно. MicroBlaze поддерживает до 16 сопроцессоров :) Да, $25 баксов современные, даже навороченные контроллеры не стоят (оценим их в $15). Но $10 разницы между ценой навороченного контроллера и FPGA стоят того, ибо гибкость и масштабируемость такого решения определяются только фантазией разработчика. В обсчем, Spartan-6 таки «порвал формат». Altera тормозит с Cyclone-IV. С учетом грядущей серии до конца 2012 28 нм чипов от Altera и Xilinx, как со встроенными Cortex-A9, так и без них, FPGA уверенно переходят в область разумной элементной базы для массовых решений. Я понимаю, что трудоемкость разработки и требования к разработчику при реализации этого пути существенно выше, но стоит напрячься, потратить (условно) 1 год в фоне на освоение технологии, как дальше особых затрат не будет. Зато гибкость полная, и за счет кучи DSP блоков ускориться можно просто немерено (на специализированных задачах). Все изложенное верно для embedded систем. С ограниченным и заранее известным числом задач. Без супер-гибкости а ля лялих и пр.