nabbla (nabbla1) wrote,
nabbla
nabbla1

Category:

Тестируем разогнанный QuatCore (2)

Подправили программу, поменяли местами [Y+2i+k] и [Y+2j+k], т.к алгоритму всё равно (одно из другого вычитается, а результат возводится в квадрат), зато не будет Read-After-Write (RAW) Hazard. Посмотрим, что из этого выходит:




Мы остановились на PC=0xF, DataBus=3, пара для исполнения:
i    [Y+2j+k]

Да, теперь в i спокойно заносится тройка, а из памяти запрашивается адрес 0x1F, поскольку Y=0x18, j=3 (и уже некоторое время :)) и k=1. И действительно, к следующей команде на шину данных подаётся y-значение (k=0 это икс, а k=1 - это игрек) третьей точки, найденной на фотоприёмной матрице, а именно -997 (=0xFC1B в доп. коде).

Следующая команда: PC=0x10, DataBus=-997, пара для исполнения:
Acc [Y+2i+k]


Здесь наблюдаем интересное взаимодействие. АЛУ сразу выдаёт сигнал busy, который подаётся на вход SrcStall модуля QuatCoreMem. Тот в ответ сбрасывает свой выход busy (иначе возможен deadlock, когда один будет ждать второго, а второй будет ждать первого). И когда АЛУ сбрасывает выход busy, выполнение продолжается, т.е QuatCoreMem понимает, что у него тоже уже сформировался правильный выход. Это хорошо :) Правда, сейчас имеем тривиальный частный случай - мы взяли то же самое значение по адресу 0x1F. Это мы упростили алгоритм ценой несколько бредовых вычислений - могли бы специально проверить i=j и пропустить прибавление квадрата разности координат, но мы очень уж жадные до памяти программ!

Следующая команда: PC=0x11, DataBus=-997, пара для исполнения:
SUB Acc


Увы, у нас опять проблемы: вычитание проходит корректно, а вот на шину данных подаётся ещё не обновлённое значение Acc, поэтому видно, как на один такт вместо нуля там образуется всё то же самое -997, и именно это значение будет возводиться в квадрат!

Вот так вот: хоть АЛУ со стороны Dest останавливается и стоит на месте, пока всё не выполнит, а вот всё равно проблема возникла. Здесь я бы, честно говоря, поставил интерлок, уж очень характерная ситуация, когда мы производим цепочку операций с АЛУ. Самое простое - если DestAddr и SrcAddr оба принадлежат АЛУ, то обеспечиваем задержку ещё на один такт. Можно сделать более сложные эвристики - если операции "короткие" (не умножения), а запрошен регистр C, то задержки не делаем, и так далее. Но для начала - более "тупую".

Была "гениальная" идея, как заставить АЛУ генерить ещё сигнал SrcStall, повторяющий DestStall, если оба операнда "принадлежат" АЛУ, даже собрал такой вариант, долго мучался с фиттером, а в итоге обнаружил, что вариант не работоспособный.

Сейчас пришёл к такому варианту, в модуле QuatCoreALUcontrol строку

assign Busy = isOurAddr & (DestAddr[4:2] != 3'b0_10)&(~isAdd)&(~finished);


заменить строками:

wire MainBusy = isOurAddr & (DestAddr[4:2] != 3'b0_10)&(~isAdd)&(~finished);	
wire AuxBusy = (SrcAddr[7:4] == 4'b1000) & (isAdd | finished);
assign Busy = MainBusy | AuxBusy;


То есть, если ранее мы специально "выкусывали" заключительный такт работы (будь то состояние sAdd или последний бит умножения), чтобы с этого момента процессор уже стронулся с мёртвой точки, то теперь, если источник данных тоже относится к АЛУ, мы продлеваем сигнал busy ещё на такт.

Правда, сразу возникает новая проблема: раз процессор остановится на ещё один такт, то выполнение команды продолжится по-новой, ведь АЛУ вернулось в состояние sIdle, при этом stall=0, а код команды тот же самый. И так мы вообще войдём в бесконечный цикл.

Чтобы справиться с этим, вводим дополнительный регистр:
reg rBusy = 1'b0;
always @(posedge clk)
	rBusy <= AuxBusy;


И чуть модифицируем определение сигнала IsOurAddr:
wire isOurAddr	   = (DestAddr[7:5] == 3'b100)&(~stall)&(~rBusy);


Вроде бы сам модуль QuatCoreALUControl от этого не шибко прибавил, с 38 ЛЭ до 42 ЛЭ - обидно, но жить можно, если это сэкономит нам десятки байт в памяти :) Я всё мечтаю о конфигурируемом трансляторе, чтобы он сначала включил все-все опции процессора, а потом увидел, что у нас остаётся свободная память в ПЗУ (мы можем её брать 512-байтовыми блоками) - и начать убирать схемотехнические навороты в пользу более толстого кода :)

Сам QuatCore на данный момент (без ввода-вывода) занимает 491 ЛЭ при ширине аккумулятора 32 бита, с отключенной командой ijk и конвейером, с шириной адресных шин по 8 бит как на ПЗУ (сегмент кода), так и на ОЗУ (сегмент данных).

А когда мы ставим QuatCoreFastALUControl (с устранением RAW Hazard по АЛУ), размер увеличивается до 494 ЛЭ. Да, он успел разжиреть с прошлого раза. 24 ЛЭ ушло на защёлки в ПЗУ, а ещё 22, похоже, на всю эту дополнительную логику. Хотя не удивлюсь, если 16 из них ушли в мультиплексор шины данных, в которой появилось 2 дополнительных входа, для внешней памяти и для ввода-вывода. Сейчас они не подключены, но логика всё равно поменялась - мы стали реагировать на 2 дополнительных бита в SrcAddr. Но всяко это очень дёшево за 6-кратное повышение производительности!

Попробуем запустить ту же самую программу на процессоре с модифицированной схемой:


Ну наконец-то! Как видно, длительность выполнения команд
SUB  Acc

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

Следующий шаг: PC=12, DataBus=0, пара для выполнения:
SQRD2   [SP]

Это САМАЯ ДЛИННАЯ операция из всех: 19 тактов.

В [SP] у нас лежит текущая сумма квадратов длин, на данный момент ноль - он и отправится на шину данных. А SQRD2 усиленно возводит ноль в квадрат и делит пополам. В аккумуляторе должен получиться ноль по логике.

Смотрим дальше, и тут всё идёт вкривь да вкось:


PC=13, DataBus=0, пара для исполнения:
ADD Acc

Мы должны добавить к аккумулятору значение [SP], которое мы извлекли на прошлом этапе, ноль. Ноль плюс ноль даст ноль по идее. И затем это значение мы должны перенести на шину данных.

И что же мы видим по окончании - ЕДИНИЦУ. Вот тебе и хвалёная 32-битная точность. Причина понятна - я забыл байпас подправить, он видя, что SrcAddr принадлежит АЛУ, подсоединяет младшие биты с выхода на вход, чтобы "расширить" шину данных с 16 бит до 31 бита. Видимо, нужно ввести такую же задержку, как на шине данных. Об этом завтра подумаем.

Но и дальше не лучше...
PC=14, DataBus=1 (о ужас), пара для исполнения:
[SP] -5

Значение 1 (а должен быть ноль) заносится в [SP], адрес в памяти верный, 0x60. Тем временем, на шину данных заносится значение -5 - это относительный адрес прыжка.

PC=15, DataBus=-5, пара для исполнения:
iLOOP -7

У нас i=3, поэтому переход выполняется. Тут же зажигается SrcDiscard=1, что делает команду "-7" недействительной, но её плевать - она всё равно поступает на шину данных.

PC=10 (переход совершён), DataBus=-7, пара для исполнения:
kLOOP [SP+1]

Здесь одновременно SrcDiscard=1 и DestDiscard=1, так что команда игнорируется ЦЕЛИКОМ. Так и надо.

PC=11 - тут происходит СБОЙ. По какой-то причине у нас сохраняется SrcDiscard=1, хотя ему уже пора было сброситься в ноль.

Ошибка в этой строке в модуле QuatCorePCAdder:
wire AnyJump = DoJump | DoAbsAddr;



А надо так:
wire AnyJump = (DoJump&(~DestDiscard)) | DoAbsAddr;


Ещё 2 ЛЭ съели почему-то, да ещё и тайминги завалили (аж 24,63 МГц, 3 "заваленных" пути), но теперь переходит правильно:



Ладно, утро вечера мудренее. Тайминги-фигня, как все "отладочные" выходы уберу (PC, SrcAddr, DestAddr) - они выправятся. Вот байпас в АЛУ надо подрихтовать, 0+0=1 это нонсенс :) А там, глядишь, уже и зафурычит.
Tags: ПЛИС, программки, работа, странные девайсы
Subscribe

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

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

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

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

  • Балансируем конвейер QuatCore

    В пятницу у нас всё замечательно сработало на симуляции, первые 16 миллисекунд полёт нормальный. А вот прошить весь проект на ПЛИС и попробовать "в…

  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your IP address will be recorded 

  • 0 comments