nabbla (nabbla1) wrote,
nabbla
nabbla1

Categories:

Ускоренный QuatCore: проверяем, что ничего не сломали :)

А то игрались с блокировками, выкидывали один мультиплексор, потом вернули его на место. Добавили новые Hazard'ы, а потом торжественно научились их отключать (чтобы раз за разом 128 команд не переправлять в конфигурационном файле). А ещё, с добавлением в рабочую программу процедур перемножения кватернионов и поворота вектора с помощью кватерниона, в кои-то веки "умный формирователь CallTable" не смог управиться совсем без логических элементов. Код, который он пишет, если без ЛЭ не обошлось, мы ещё не проверяли, могут быть проблемы...


С Hazard'ами особых проблем быть не должно. Добавили новую строку в файл конфигурации:

UTF8object TQuatCoreTranslator
  RelJumpLatency = 2
  ActiveHazards = [crAcc, crC, crX, crY, crZ, crSP, cri, crj, crk, crInv, crMemBus]
  object TQuatCoreCommand
    Key = 'OUT'
    Code = 0
    Mask = 224
    Description = 'Sends value to chosen output'
    Place = [cpDest]
    Resources = []
    DataType = dtNumeric
  end
...
...


И затем в своём коде проверки Hazard'ов добавили кусочек:
if (prevDest.Resources * v.Resources * ActiveHazards <> []) and not (prevSrc.CreatesBubble) then begin
...


Ясно, что мы могли бы при загрузке файла конфигурации уже произвести умножение (пересечение множеств), но вдруг мы захотим позволить транслятору самому решать, включать ли аппаратные блокировки в процессор, или лучше просто добавить NOPы здесь и там. Скажем, если у нас получилось 258 слов кода, и мы чуть-чуть не влезли в один Блок Внутренней Памяти (Embedded Array Block, EAB) размером 512 байт, то логика подсказывает чуть усложнить логику, зато сэкономить 512 байт, лучше этот блок где-то ещё задействовать, в обработке видео они будут улетать как горячие пирожки. Тогда строка ActiveHazards будет меняться "на ходу". Не знаю, когда до этого дойдут руки, пока не горит.

Теперь глянем, что там происходит с таблицей вызова процедур (CallTable).

В журнале транслятора находим следующие "пометки":
Пытаемся оптимизировать таблицу вызова процедур
NormSiCo     = 00A2 
QuatMultiply = 00B7 
ShiftOrigin  = 009A 
SwapPoints   = 0093 

Бит 7 адреса
Всегда единица...
Бит 6 адреса
Всегда ноль...
Бит 5 адреса
не повторяет предыдущих (сигнатура 12)
Сопоставление его биту SrcAddr[3] прошло успешно
Бит 4 адреса
не повторяет предыдущих (сигнатура 7)
Сопоставление его биту SrcAddr[2] прошло успешно
Бит 3 адреса
не повторяет предыдущих (сигнатура 2)
Сопоставление его биту SrcAddr[1] прошло успешно
Бит 2 адреса
не повторяет предыдущих (сигнатура 4)
Сопоставление его биту SrcAddr[0] прошло успешно
Бит 1 адреса
Всегда единица...
Бит 0 адреса
не повторяет предыдущих (сигнатура 5)
но биты SrcAddr уже закончились...
1 выходных бит выражаются через входные посредством ЛЭ
Компиляция завершена успешно


Итак, следующие адреса были сопоставлены 4 битам:

1010_0010:   1000
1011_0111:   1101
1001_1010:   0110
1001_0011:   0100


Все записи из журнала подтверждаются: бит 7 всегда единичный, бит 6 всегда нулевой, затем идут "неповторимые" биты с 5 по 2, которые переносятся в биты номера команды. Бит 1 всегда единичный, а вот для бита 0 нужна логическая функция.

Посмотрим, наконец, на автоматически сгенерированный код на верилоге:
//адреса для вызова процедур, "вшитые" в модуль QuatCorePC
module QuatCoreCallTable (input [7:0] SrcAddr, output [RomWidth-1:0] addr);
parameter RomWidth = 8;
	assign addr[7]=1'b1;
	assign addr[6]=1'b0;
	assign addr[5]=SrcAddr[3];
	assign addr[4]=SrcAddr[2];
	assign addr[3]=SrcAddr[1];
	assign addr[2]=SrcAddr[0];
	assign addr[1]=1'b1;
	wire [3:0] index = SrcAddr[3:0];
	assign addr[0]=
		(index == 4'h8)? 1'b0:
		(index == 4'hD)? 1'b1:
		(index == 4'h6)? 1'b0:
			1'b1;
//Адреса процедур:
// NormSiCo     = 00A2(поле Src = B8) 
// QuatMultiply = 00B7(поле Src = BD) 
// ShiftOrigin  = 009A(поле Src = B6) 
// SwapPoints   = 0093(поле Src = B4) 
endmodule


По крайней мере, этот код корректен. Тут никуда не денешься, 1 ЛЭ нужен. Разве что можно было побороться за количество входов этого ЛЭ, если их будет 2, то, возможно, он будет включён состав последующей логики. Здесь мы могли бы использовать лишь 2 входа, но пока реализовывать подобные вещи мне лениво.

Попробуем отсинтезировать наш процессор
Никаких проблем: на весь процесс компиляции уходит 3,5 минуты на моём "офигительно быстром" Intel Atom D510 :) И тайминги выдерживаются: 25,77 МГц, а всего этот процессор умещается в 492 ЛЭ. Да, чуть он подрос при "ускорении", но не сильно.

Запустим симуляцию



Как говорится, "найдите 10 отличий" с этим.

То же время выполнения, тот же результат. Уже радость.


Всё-таки, на веранде как-то резвее работалось, чем на втором этаже. Тут света пока маловато. Сегодня наконец-то поднарастил до 6 светодиодов, 3 из них питаются током 0,7 ампера, ещё 3 - током 2,5 ампера, в общей сложности выходит 32 Вт "чистыми", свыше 3200 люмен должно выходить, но здесь светодиоды светят в белый потолок, а уже от него рассеивается во все стороны. Получается очень равномерно, буквально "хирургический свет" без теней, но не очень ярко.

И в целом, очень неохота эти "хвосты закрывать". Может, сейчас возьмусь за I/O, оно повеселее пойдёт.
Tags: ПЛИС, программки, работа, странные девайсы
Subscribe

  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your IP address will be recorded 

  • 0 comments