March 9th, 2021

QuatCore

Испытания новой АЛУ, часть 0

Стряхнём пыль с аффинного алгоритма, и попробуем его запустить на QuatCore с новой АЛУ. Ну, АЛУ не совсем новая, изменения коснулись преимущественно модуля управления.

Начнём с первой процедуры, "поиск самой отдалённой точки". У нас этих точек обнаружено 4 штуки, для каждой указаны координаты. Мы находим одну точку, стоящую "особняком" - это будет Мишень Дальней Дистанции - 3 (МДД3). Для этого просто ищем сумму квадратов дальностей от каждой точки до всех остальных точек. Такая вот программка:

;состояние регистров неизвестно (за искл. PC и SP)
FindMDD3	proc
;перво-наперво, находим МДД3
;как точка, сумма квадратов расстояний до которой максимальна (т.е самая отдалённая)
;для каждой точки считаем сумму квадр. расстояний до всех остальных, в т.ч до самой себя (это 0, зато код упрощается)
;внешний цикл (по строкам) - перем. j
;внутр. цикл - по индексу перем (X или Y) - перем k
;самый-самый внутр. цикл (по столбцам) - перем. i
		Y	Points2D
		[SP+1]	0	;максимальная отдалённость, инициализируем нулём
		;рег. X будет хранить индекс точки с макс. отд. её иниц. не надо-заведомо на одной из итераций запишется
					
		j	3
@@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],
;а его индекс - в X
		SUB	[SP+1]	;можно и "пожертвовать" значением в Acc,
;т.к в [SP] лежит точно такое же!
		JL	@@skip
;дистанция оказалась больше - надо обновить максимум и его индекс
		[SP+1]	[SP]	;двухпортовая память-это зашибись!
		X	j
@@skip:		jLOOP	@@j_loop
;по окончании этих циклов, у нас в X лежит индекс точки, которая является МДД3
;осталось эту точку поменять местами с точкой под индексом 0...
;здесь i=j=k=0 (все циклы завершились!)
		i	X
		X	Points2D
		Z	Points2D
		CALL	SwapPoints	;потёрли текущий максимум (лежал в [SP])-и хрен с ним
		
;на этом первая часть марлезонского балета закончена.
FindMDD3	endp


За быстродействием тут явно не гнались, эта операция выполняется один раз за кадр, и даже на 4 МГц проблем не было. Скорее, гонка была за простотой и компактностью кода: пусть мы по несколько раз посчитаем одни и те же квадраты, в том числе заведомые нули (когда i=k), зато лишних условий и хитрючих манипуляций с памятью нет.

На "старом" АЛУ всё это дело (до прыжка в SwapPoints) выполняется за 47,36 мкс при тактовой частоте 25 МГц. Для введённых сейчас точек:
;дистанция 300 метров, все углы нулевые
Fx0		Int16 53
Fy0		Int16 -7

Fx1		Int16 480
Fy1		Int16 -30

Fx2		Int16 -539
Fy2		Int16 -302

Fx3		Int16 400
Fy3		Int16 -997


самой отдалённой оказалась последняя - всё верно.

Посмотрим сначала, какого ускорения можем ждать от новой АЛУ, и можно ли чуть подрихтовать код, чтобы он воспользовался преимуществами. Как ни странно - без увеличения размера кода это практически нереально!

Collapse )

Что ж, начало многообещающее, но глюки есть. Может, это и хорошо. Заработай оно вообще с первого раза - это было бы очень подозрительно...