nabbla (nabbla1) wrote,
nabbla
nabbla1

Category:

Недокументированная команда KILL

С новым годом!

Начинаю разбираться с вычислительным ядром QuatCore в сборе. Отдельные модули худо-бедно были отработаны. В каждом из них было некоторое количество незадействованных "команд" (адресов), некоторые просто дублировали уже имеющиеся команды, некоторые представали странным симбиозом. Кроме того, мы считали нормальным явлением всегда что-то подавать на выход, даже если команда адресована "не нам", поскольку наш выход всё равно упирается в мультиплексор, который подключает к шине данных один из 4 модулей - тот, который в данный момент назначен источником данных (Src).

Но когда мы собрали всё воедино, обнаружилось, что некоторая хитро собранная недокументированная команда может нанести ФИЗИЧЕСКОЕ ПОВРЕЖДЕНИЕ кристаллу! Или, на худой конец, вызвать повышенное энергопотребление "на ровном месте". Причём, оба адреса, Dest и Src - совершенно законные, просто их совместное использование в одной инструкции не предполагалось из-за своей абсурдности...


Речь идёт о модуле QuatCorePC - счётчике инструкций. Чтобы упростить программный код, мы решили сделать аж три разных типа "прыжков":

- прыжок по абсолютному адресу, JMP,
- прыжок по относительному адресу, по условию, JL/JGE/JO/JNO/Jik/iLOOP/jLOOP/kLOOP,
- вызов функции, адрес берётся из модуля CallTable, входящего в состав QuatCorePC, и адреса в него заносятся компилятором.

И если первые два типа прыжков запускаются соответсвующими адресами Dest, что довольно логично (мы как бы присваиваем счётчику инструкций PC, program counter, новое значение, по определённым правилам), то вызов функции запускается адресом Src. В данном случае на шину данных поступает адрес возврата, чтобы поместить его в стек, а выполнение прыжка является "побочным эффектом".

Подлянка наступает, когда мы комбинируем эти адреса, давая команду наподобие
JL CALL0

Ещё разок приведу здесь схему модуля (подробности здесь):


Сам по себе регистр PC вовсе не "впадёт в ступор" из-за противоречащих инструкций, а-ля компьютеры, которых уничтожает капитан Кирк. Здесь никакого противоречия нет, в коде прописан приоритет "вызова процедуры" перед прочими прыжками:

Q <= 	reset? 		{RomAddrWidth{1'b0}} :
	DoCall? 	CallAddr :
	DoAbsAddr? 	DataBus[RomAddrWidth-1:0] :
			RelAddr;


так что здесь никаких проблем.

Модуль QuatCorePCadder, который либо оставляет адрес "как есть" (если мы застряли на инструкции), или прибавляет единичку при "нормальном ходе вещей", или прибавляет значение из шины данных, чтобы из относительного адреса получить абсолютный, и думать не хотел об адресе SrcAddr, это не его дело. Им управляет сигнал busy, заставляя "стоять на месте", а если busy=0, то сигнал DoJump - он определяет, нужно ли выполнять переход по относительному адресу, и формируется модулем QuatCorePCrelJumpDecision исходя из адреса Dest (была ли выбрана одна из команд условного перехода) и набора флагов (выполняются ли условия для этого перехода). Если в нашей ситуации мы выбрали такую команду, для которой условие будет выполняться, то DoJump=1, и к выходу PC будет прибавляться вход с шины данных D.

Результирующее значение будет игнорироваться самим регистром PC - он вместо этого загрузит CallTable[0]. Но оно поступит на выход модуля, поскольку "в нормальных обстоятельствах" мы не используем несколько типов перехода одновременно, и выходом данного модуля должно быть PC+1, т.е адрес возврата.

Но здесь вместо PC+1, мы получаем PC+D, оно и отправляется на выход модуля.

И в этот раз мультиплексор выберет именно его, т.к и DestAddr, и SrcAddr принадлежат этому модулю.

В итоге СУММАТОР ЗАКОРОТИТСЯ САМ НА СЕБЯ! Т.е его выход будет напрямую, минуя какие-либо регистры, поступать на один из своих входов. Это так называемый combinatorial loop. Что из этого выйдет - сложно предсказать. Оно может "защёлкнуться" в каком-то стабильном состоянии, может застрять посередине, потребляя жуткие сквозные токи (КМОП-логика ничего не потребляет, когда у нас четкий логический уровень, 0 или 1, но оба ключа, верхний и нижний, открываются, если мы располагаемся где-то посередине). Либо, возможен "самовозбуд", когда вся схема станет генератором, причём генерить она скорее всего будет на частоте куда выше рабочей. Если рабочая частота - такая, во время которой бит переноса в 32-битном сумматоре успевает распространиться через все разряды, и затем правильное 32-битное слово поступить в регистр и там "защёлкнуться" (т.е ищем САМЫЙ ДЛИННЫЙ ПУТЬ и выбираем с запасом), то здесь скорее периодом будет время прохождения по САМОМУ КОРОТКОМУ ПУТИ, так что немудрено здесь напороться на сотни МГц, при "нормальной" частоте в 50..80 МГц. Разумеется, греться на такой частоте оно будет гораздо сильнее, у нас же кристалл вообще сколько-нибудь зверского теплоотвода не имеет, считается, что на нём будет выделяться от силы 1 Вт.

Конечно, если мы за один такт покинем "проклятое место", то ничего страшного не произойдёт. Но если уж мы совсем с дуба рухнули и указали адресом прыжка ту же самую команду ("рекурсивный вызов"), то можно и правда что-нибудь пожечь.

Сейчас чуточку подправил этот модуль, а именно, ввёл в QuatCorePCadder "провод" CALL, чтобы условием прибавления D было CALL=0, DoJump=1. Всё, синтезатор успокоился и не пугает предупреждениями о Combinatorial loop.

Только вот нехорошую вещь заметил - почему-то далеко не всегда при синтезе он правильно передаёт PARAMETER вглубь модулей. Я меняю ширину аккумулятора с 32 до 19, запускаю синтез - а ничего не меняется. Удаляю модуль, ещё разок для надёжности создаю schematic symbol, снова ставлю его на общую схему - тогда работает. Немножко странно квартус эти вещи обрабатывает.


UPD. Есть по крайней мере один производитель ПЛИС, который в своём ПО запрещает прошивать "схемы", в которых содержатся combinatorial loops, именно из страха что-нибудь подпалить. С другой стороны, в Altera Cookbook рассматривается, как на основе этих самых "комбинаторных обратных связей" можно сделать внутри ПЛИС генератор ИСТИННО случайных чисел. "Мой" чип, 5576ХС4Т2, является функциональным аналогом альтеровского, наверное должен выжить, но проверять как-то не хочется!
Tags: ПЛИС, работа, странные девайсы
Subscribe

  • Я создал монстра!

    Вот нормальная счастливая пара разъёмов ОНЦ-БС-1-10/14-Р12-2-В и ОНЦ-БС-1-10/14-В1-2-В: У розетки кроме основного выступа, отмечающего "верх",…

  • Нахождение двух самых отдалённых точек

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

  • Слишком общительный счётчик

    Вчера я чуть поторопился отсинтезировать проект,параметры не поменял: RomWidth = 8 вместо 7, RamWidth = 9 вместо 8, и ещё EnableByteAccess=1, чтобы…

  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your IP address will be recorded 

  • 15 comments

  • Я создал монстра!

    Вот нормальная счастливая пара разъёмов ОНЦ-БС-1-10/14-Р12-2-В и ОНЦ-БС-1-10/14-В1-2-В: У розетки кроме основного выступа, отмечающего "верх",…

  • Нахождение двух самых отдалённых точек

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

  • Слишком общительный счётчик

    Вчера я чуть поторопился отсинтезировать проект,параметры не поменял: RomWidth = 8 вместо 7, RamWidth = 9 вместо 8, и ещё EnableByteAccess=1, чтобы…