nabbla (nabbla1) wrote,
nabbla
nabbla1

Category:

QuatCore: оттачиваем прыжки

Да я на таких как ты в Марио сверху прыгал!

Стремительным домкратом двигаем дальше. Вызов процедуры видели - работает как надо. Работу с памятью и АЛУ глянули, подрихтовали здесь и там - тоже работает.

Теперь настаёт пора прыжков. Мне казалось, что с ними всё в порядке, оказалось, что казалось.



Мы будем работать со следующим кодом:

		@@j_loop:	k		1	;также от 0 до 3, чтобы все расстояния просуммировать
				[SP]		0	;здесь будет храниться текущий максимум
		@@k_loop:	i		3	;от 0 до 1, т.е значения X и Y
		;а теперь непосредственно прибавляем к акк. ([X+2i+k]-[X+2j+k])^2
		@@i_loop:	Acc		[Y+2j+k]	;загрузили одно значение
				SUB		[Y+2i+k]	;вычитаем второе
				SQRD2		Acc			;возводим в квадрат
				ADD		[SP]		;прибавляем к пред. значению
				[SP]		Acc
				iLOOP		@@i_loop		;теперь то же самое для второй координаты
				kLOOP		@@k_loop
		;хорошо, нашли сумму расстояний от точки j до всех остальных
		;она лежит в Acc и в [SP]
		;нужно сравнить с самым большим, и если больше - заменить
		;самое большое значение мы храним в [SP+1],
		;а его индекс - в [SP+2]
				SUB		[SP+1]	;можно и "пожертвовать" значением в Acc,
		;т.к в [SP] лежит точно такое же!
				JL		@@skip
		;дистанция оказалась больше - надо обновить максимум и его индекс
				[SP+1]		[SP]	;двухпортовая память-это зашибись!
				X		j
		@@skip:		jLOOP		@@j_loop
		;по окончании этих циклов, у нас в Y лежит индекс точки, которая является МДД3
		;осталось эту точку поменять местами с точкой под индексом 0...
		;здесь i=j=k=0 (все циклы завершились!)
				i		X
				X		Points2D
				Z		Points2D
				CALL		SwapPoints	;потёрли текущий максимум (лежал в [SP])-и хрен с ним
		
		;на этом первая часть марлезонского балета закончена.
		FindMDD3	endp
	Associate4Points endp

			JMP			[--SP]
AffineAlgorithm 	endp

;меняет местами точку с базой Z, инд. j  и базой X, инд. i
;изменяет регистр k (по окончании выходит 0), и C, Acc
SwapPoints	proc
		k		1
@@swap:		C		[Z+2j+k]
		[Z+2j+k]	[X+2i+k]
		[X+2i+k]	C
		kLOOP		@@swap
		JMP		[--SP]
SwapPoints	endp	


Мы как раз мучительно добрались до iLOOP - достали два числа из памяти (и сейчас, поскольку j=i=3, это оказалось одно и то же число), вычли одно из другого, возвели в квадрат, прибавили к общей сумме, лежащей в [SP], и сейчас хотим сделать то же самое, но с i=2..0.

И тут же замечаем подлянку, ошибку на 2. Вот листинг интересующей нас части программы:
0B  A201          @@j_loop:   k       1   ;также от 0 до 3, чтобы все расстояния просуммировать
0C  FC00                      [SP]    0   ;здесь будет храниться текущий максимум
0D  A003          @@k_loop:   i       3   ;от 0 до 1, т.е значения X и Y
0E  80DA          @@i_loop:   Acc     [Y+2j+k]    ;загрузили одно значение
0F  83D9                      SUB     [Y+2i+k]    ;вычитаем второе
10  9C80                      SQRD2   Acc         ;возводим в квадрат
11  82FC                      ADD     [SP]        ;прибавляем к пред. значению
12  FC80                      [SP]    Acc
13  A87B                      iLOOP   @@i_loop        ;теперь то же самое для второй координаты
14  AA79                      kLOOP   @@k_loop
15  83F0                      SUB     [SP+1]  ;можно и "пожертвовать" значением в Acc,
16  B003                      JL      @@skip
17  F0FC                      [SP+1]  [SP]    ;двухпортовая память-это зашибись!
18  CDA1                      X       j
19  A972          @@skip:     jLOOP   @@j_loop
1A  A0CD                      i       X
1B  CD18                      X       Points2D
1C  ED18                      Z       Points2D
1D  F3B1                      CALL    SwapPoints  ;потёрли текущий максимум (лежал в [SP])-и хрен с ним


Мы видим, что iLOOP находится по адресу 0x13, а перейти мы хотим на адрес 0x0E. Вычитая одно из другого, получили когда-то относительный адрес -5.

Но теперь посмотрим, что выходит в процессоре. Когда дело дошло до прыжка, уже было PC=15. И модуль QuatCorePC честно отнял 5 и получил новое значение PC=10. И именно команда по этому адресу (после выкидывания случайно затесавшихся по PC=14 и PC=15) начала выполняться, опять напрочь убив наш алгоритм.

Промахнулись на 2 позиции!

Здесь я считаю, что сам процессор рихтовать не надо - отрихтовать надо транслятор, чтобы из относительного адреса ещё вычитал двойку. Введу отдельный параметр в конфигурационном файле, чтобы мог делать программы как для старого QuatCore (его я сохранил), так и для ускоренного.

Теперь для той же самой части программы получаем следующий листинг:

0B  A201      @@j_loop:   k       1   ;также от 0 до 3, чтобы все расстояния просуммировать
0C  FC00                  [SP]    0   ;здесь будет храниться текущий максимум
0D  A003      @@k_loop:   i       3   ;от 0 до 1, т.е значения X и Y
0E  80DA      @@i_loop:   Acc     [Y+2j+k]    ;загрузили одно значение
0F  83D9                  SUB     [Y+2i+k]    ;вычитаем второе
10  9C80                  SQRD2   Acc         ;возводим в квадрат
11  82FC                  ADD     [SP]        ;прибавляем к пред. значению
12  FC80                  [SP]    Acc
13  A879                  iLOOP   @@i_loop        ;теперь то же самое для второй координаты
14  AA77                  kLOOP   @@k_loop
15  83F0                  SUB     [SP+1]  ;можно и "пожертвовать" значением в Acc,
16  B001                  JL      @@skip
17  F0FC                  [SP+1]  [SP]    ;двухпортовая память-это зашибись!
18  CDA1                  X       j
19  A970        @@skip:   jLOOP   @@j_loop
1A  A0CD                  i       X
1B  CD18                  X       Points2D
1C  ED18                  Z       Points2D
1D  F3B1                  CALL    SwapPoints  ;потёрли текущий максимум (лежал в [SP])-и хрен с ним


Коды поменялись. Если раньше @@i_loop транслировался в 0x7B, это 7-битное число в дополнительном коде, выражающее "-5", то теперь здесь 0x79, т.е уже "-7". А позже мы видим прыжок вперёд, @@skip, который раньше транслировался в 03, а теперь в 01.

Пробуем снова запустить это дело на симуляции:


Совсем другое дело!
PC=0x14:
[SP]  -7

В [SP] заносим текущую сумму квадратов разностей координат, сейчас это ноль. На шину данных заносим число -7.

PC=0x15:
iLOOP  -9

Поскольку i=3, больше нуля, то переход происходит, к PC прибавляется значение с шины данных, -7. Включается SrcDiscard=1, т.е значение "-9" объявляется недействительным, но всё равно поступает на шину данных.

PC=0x0E:
kLOOP [SP+1]

Как видно, прыжок действительно произошёл туда, куда и планировали. Но на конвейере пока проматываются ненужные команды - ни kLOOP, ни [SP+1] мы исполнять не будем!

PC=0x0F:
SUB [Y+2j+k]

SUB мы игнорируем, а вот [Y+2j+k] выполняем. Как видно, обращаемся по адресу 0x18+2*3+1 = 0x1F, всё верно. На шину приходит значение -997 = 0xFC1B.

PC=0x10:
Acc [Y+2i+k]

Всё, наконец-то мы заработали в полную силу! В аккумулятор заносится значение -997, и тем временем запрашивается адрес 0x18+2*2+1=0x1D, и на шину с него приходит значение 0xFED2 = -302.

PC=0x11:
SUB Acc

Вычитаем значение -302, т.е -997-(-302) = -695. И именно результат этого мы хотим увидеть на шине данных. Срабатывает интерлок, и выполнение затягивается на такт, получаем значение FD49. Это в доп. коде и есть -695 - отлично. Мы научились считать :)

PC=0x12:
SQRD2  [SP]

Значение -695 возводим в квадрат и делим на два. Тем временем, на шину данных заносим значение из [SP], там у нас лежит нолик.

PC=0x13:
ADD   Acc

К получившемуся значению прибавляем нолик из шины данных, и именно результат действия хотим увидеть на шине данных.

Следующий слайд!


Как и ожидалось, выполнение команды заняло одним тактом больше за счёт интерлока. На выходе получили значение 7. Действительно,

(-695/32768)2/2 = 7,37/32768,

так что в нашем формате чисел 1.15 вычисления исполнились чётко.

Далее этот промежуточный результат мы заносим в [SP], снова прыгаем и выполняем итерацию для i=1.
Адрес [Y+2j+k] остался неизменным, 0x1F, с тем же значением -997. Адрес [Y+2i+k] теперь 0x18+2*1+1=0x1B, и лежит там значение 0xFFE2=-30. После вычитания получается -967 = 0xFC39. На шину данных поступает значение из [SP], это "7".

Следующий слайд!

Устал добавлять надписи, уже почти что наизусть коды инструкций запомнил. Ох, плачет по мне психушка.

Итак, результатом возведения в квадрат и деления пополам должно стать

(-967/32768)2/2 = 14,27/32768,

и прибавляем к 7 - должно выйти 21 = 0x15. Да, так и есть, и это значение отправляется в [SP]. Осуществляем очередной прыжок, теперь уже i=0. Адрес [Y+2j+k] остался прежним, 0x1F, с тем же значением -997. Адрес [Y+2i+k] теперь 0x18+2*0+1=0x19, и лежит там значение 0xFFF9 = -7. После вычитания получается -990 = 0xFC22. Тем временем, из [SP] извлекаем значение 0x15.

Следующий слайд!


В результате возведения в квадрат и деления пополам должно получиться:

(-990/32768)^2/2 = 14,95 / 32768,

и прибавляем 21 - должно выйти 36 = 0x24. Да! Округление (14,95 до 15) работает корректно! Заносим это значение в [SP], и начинаем выполнять iLOOP. Но в этот раз i=0, поэтому прыжка не происходит, и мы идём дальше. А вот kLOOP срабатывает, поскольку k=1. Осуществляется переход на адрес 0x0D. По листингу видим, что именно там стоит метка @@k_loop:. Т.е, сюда нам и надо. И k должен уменьшиться до нуля. Далее видим, как две команды проходят "вхолостую" за счёт SrcDiscard и DestDiscard. Наконец, мы заносим число 3 в шину данных, а затем возобновляется полноценная работа. Число 3 присваивается регистру i, и мы опять выходим на тот же внутренний цикл.

В этот раз оба адреса, Y+2j+k и Y+2i+k одинаковые и равны 0x18+2*3+0 = 0x1E. По этому адресу лежит число 0x0190=400. Вычитая его из самого себя, получаем ноль (ВНЕЗАПНО), а возводя его в квадрат, снова получаем ноль, а тем временем достаём из [SP] нашу сумму, 0x24.


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

Ща отдышимся и пойдём дальше смотреть выполнение, но, надеюсь, более "галопом". Там ещё интересные места намечаются, с пересылками "память-память" :)
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