nabbla (nabbla1) wrote,
nabbla
nabbla1

Categories:

Транслятор QuatCore поумнел!

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

Загружаем файл конфигурации транслятора
Файл конфигурации прочитан, готовы к работе
Обрабатываем файл OurProgramForFastCPU.asm
Конфликт (Hazard) между командами [Y+1] и [--SP], процедура AffineAlgorithm, строки:
				[Y+1]		0
			JMP			[--SP]
Вставляем NOP

Пытаемся оптимизировать таблицу вызова процедур
AffineAlgorithm = 000D 
NormSiCo        = 0074 
ShiftOrigin     = 006C 
SwapPoints      = 0065 

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

Ширина адреса сегмента кода (и регистра PC):           7   
Ширина адреса сегмента данных (и регистров X,Y,Z,SP):  8   
Количество инициализированных слов данных:             189 
Количество инициализированных слов кода:               127 
Количество адресов процедур:                           4   

Адреса процедур:
AffineAlgorithm = 000D(поле Src = B3) 
NormSiCo        = 0074(поле Src = BC) 
ShiftOrigin     = 006C(поле Src = BA) 
SwapPoints      = 0065(поле Src = B9) 


По крайней мере, когда удаётся вообще обойтись без логических элементов, всё срабатывает как надо. Другие варианты пока ещё не тестировал, на ходу буду :)


А вот verilog-файл, который теперь генерируется:

//адреса для вызова процедур, "вшитые" в модуль QuatCorePC
module QuatCoreCallTable (input [7:0] SrcAddr, output [RomWidth-1:0] addr);
parameter RomWidth = 7;
	assign addr[6]=SrcAddr[3];
	assign addr[5]=addr[6];
	assign addr[4]=SrcAddr[2];
	assign addr[3]=SrcAddr[1];
	assign addr[2]=1'b1;
	assign addr[1]=1'b0;
	assign addr[0]=SrcAddr[0];
endmodule


И листинг кода:

main proc
00  FD47              SP      StackAdr
01  8900              NOP     0       ;избежать Write Hazard: только здесь в SP запишется новое значение!
02  FDFC              SP      [SP]
03  F3B3              CALL        AffineAlgorithm
04  A203              k       3
05  ED73              Z       QuatA
06  00C8      @@xloop:    OUT     [X+k]       ;преобр. матрица 2х2
07  AA7D              kLOOP       @@xloop
08  A203              k       3
09  8900              NOP     0
0A  00E8      @@zloop:    OUT     [Z+k]       ;кватернион ориентации
0B  AA7D              kLOOP       @@zloop
0C  B00C  @@endless:  JMP     @@endless
main endp
AffineAlgorithm     proc
    Associate4Points    proc
        FindMDD3    proc
0D  DD18                  Y       Points2D
0E  F000                  [SP+1]  0   ;максимальная отдалённость, инициализируем нулём
0F  A103                  j       3
10  A201          @@j_loop:   k       1   ;также от 0 до 3, чтобы все расстояния просуммировать
11  FC00                  [SP]        0   ;здесь будет храниться текущий максимум
12  A003          @@k_loop:   i       3   ;от 0 до 1, т.е значения X и Y
13  80DA          @@i_loop:   Acc     [Y+2j+k]    ;загрузили одно значение
14  83D9                  SUB     [Y+2i+k]    ;вычитаем второе
15  9C80                  SQRD2       Acc         ;возводим в квадрат
16  82FC                  ADD     [SP]        ;прибавляем к пред. значению
17  FC80                  [SP]        Acc
18  A879                  iLOOP       @@i_loop        ;теперь то же самое для второй координаты
19  AA77                  kLOOP       @@k_loop
1A  83F0                  SUB     [SP+1]  ;можно и "пожертвовать" значением в Acc,
1B  B801                  JL      @@skip
1C  F0FC                  [SP+1]  [SP]    ;двухпортовая память-это зашибись!
1D  CDA1                  X       j
1E  A970          @@skip: jLOOP       @@j_loop
1F  A0CD                  i       X
20  CD18                  X       Points2D
21  ED18                  Z       Points2D
22  F3B9                  CALL        SwapPoints  ;потёрли текущий максимум (лежал в [SP])-и хрен с ним
        FindMDD3    endp
        SortCCW     proc
23  CD1A                  X       Fx1 ;чтобы индекс от 2 до 0 соотв. точкам (Fx1,Fy1) ... (Fx3, Fy3)
24  ED1C                  Z       Fx2 ;чтобы иметь сдвинутую на 1 адресацию
25  F3BA                  CALL        ShiftOrigin
26  A101                  j       1
27  A001                  i       1
28  8AEA          @@loop: C       [Z+2j+k]
29  90C1                  MUL     [X+2i+1]
2A  8AE2                  C       [Z+2j+1]
2B  93C9                  FMS     [X+2i+k]    ;нахождение "векторного произведения"
2C  B800                  JL      @@skip
2D  F3B9                  CALL        SwapPoints
2E  A878          @@skip: iLOOP       @@loop
2F  A977                  jLOOP       @@loop
30  F3BA                  CALL        ShiftOrigin     
31  CD1E                  X       Fx3
32  F3B9                  CALL        SwapPoints
        SortCCW     endp
    Associate4Points endp       
    Compute4PointAffine proc
33  CD33                  X       AffineMat
34  ED48                  Z       Matrix ;вообще AfTransf, но это промежуточная матрица, её занесём сюда (пока не наступило сопровождение, эти ячейки напрочь не нужны!)
35  A201                  k       1   ;номер строки результата (и строки AffineMat)
36  A102          @@k_loop:   j       2   ;номер столбца результата (и столбца Points2D)
37  A003          @@j_loop:   i       3   ;номер столбца AffineMat и строки Points2D
38  8803                  ZAcc        RoundZero   ;обнулить до 1/2 мл. разр
39  8AC7          @@i_loop:   C       [X+4j+i]
3A  92D9                  FMA     [Y+2i+k]
3B  A87C                  iLOOP       @@i_loop
3C  EA80                  [Z+2j+k]    Acc
3D  A978                  jLOOP       @@j_loop
3E  AA76                  kLOOP       @@k_loop
    Compute4PointAffine endp
    FindRoll    proc
3F  DD75                  Y       QuatY   ;в этом кватернионе построим,используя Y/Z значения как временные
40  A001                  i       1
41  A103                  j       3
42  80E4          @@sico: Acc     [Z+i]
43  A3A0                  Inv     i
44  81EC                  PM      [Z+i^j]
45  D480                  [Y+i]       Acc
46  A87A                  iLOOP       @@sico
47  F3BC                  CALL NormSiCo
48  84D8                  ABS     [Y+k]
49  CD63                  X       OneHalf             
4A  8C80                  DIV2        Acc
4B  82C8                  ADD     [X+k]
4C  BC00                  JGE     @@skip
4D  A001                  i       1       ;выходит i=S
4E  CD73          @@skip: X       QuatA
4F  C480                  [X+i]       Acc
50  A101                  j       1
51  8CD0                  DIV2        [Y+1]
52  DD73                  Y       QuatA
53  CC80                  [X+i^j] Acc         ;по сути, Y+(~S)
54  F3BC                  CALL        NormSiCo    ;подготовили первые 2 компонента кватерниона
55  DD75                  Y       QuatY
56  CD4E                  X       AfTransf    ;сюда результат складируем
57  A001                  i       1   ;номер строки результата, и строки co/si
58  A201          @@i_loop:   k       1   ;номер столбца результата, и столбца AfTransf
59  A101          @@k_loop:   j       1   ;номер столбца co/si и строки AfTransf
5A  8803                  ZAcc        RoundZero   ;обнулить до 1/2 мл. разр
5B  8ADC          @@j_loop:   C       [Y+i^j] 
5C  91EA                  FMPM        [Z+2j+k]
5D  A97C                  jLOOP       @@j_loop
5E  C980                  [X+2i+k]    Acc
5F  AA78                  kLOOP       @@k_loop
60  A876                  iLOOP       @@i_loop
61  D800                  [Y+k]       0
62  D000                  [Y+1]       0
    FindRoll    endp
63  8900      NOP  0 ;AUTOMATICALLY INSERTED BY TRANSLATOR TO PREVENT HAZARD
64  B0FF              JMP         [--SP]
AffineAlgorithm     endp
SwapPoints  proc
65  A201              k       1
66  8900              NOP     0   ;хотим избежать warning'ов
67  8AEA  @@swap:     C       [Z+2j+k]
68  EAC9              [Z+2j+k]    [X+2i+k]
69  C983              [X+2i+k]    C
6A  AA7B              kLOOP       @@swap
6B  B0FF              JMP     [--SP]
SwapPoints  endp    
ShiftOrigin proc
6C  A201                  k       1
6D  A002  @@k_loop:           i       2   ;как всегда, чтобы Y и X
6E  80D8  @@i_loop:           Acc     [Y+k]
6F  83C9                  SUB     [X+2i+k]
70  C980                  [X+2i+k]    Acc
71  A87B                  iLOOP       @@i_loop
72  AA79                  kLOOP       @@k_loop
73  B0FF                  JMP     [--SP]
ShiftOrigin endp
NormSiCo    proc
74  A10C          j       12 ;если "передавать" j как аргумент, то можно регулировать число итераций
75  8802  @@norm: ZAcc        ThreeHalf       ;выставить 3/2
76  9FD0          SQRSD2  [Y+1]
77  9FD4          SQRSD2  [Y+i]   ;вычесть половину от квадрата 
78  A001          i       1
79  8A82          C       UAC
7A  94D4  @@inmult:   MULSU       [Y+i]   ;уможение знакового B на беззнак. C
7B  D480          [Y+i]       Acc     ;вернули на место!
7C  A87C          iLOOP       @@inmult        
7D  A976          jLOOP       @@norm
7E  B0FF          JMP     [--SP]
NormSiCo    endp


Чего-то задолбали меня TABы - каждый редактор считает своим долгом выставить свой размер отступа, а в другом открываешь - всё сползает непотребно. Хоть на пробелы заменяй, по-моему где-то есть такая опция :)

Но главное, теперь команды для вызова процедур подставляются правильные, не эти ваши попсовые B0, B1, B2, B3, а чуть поинтереснее.

И за счёт упростившегося модуля QuatCoreCallTable, увеличилась предельная частота аж до 27,62 МГц. Пора запустить эту программу на симуляторе, уже на штатных 25 МГц.



Да, работает! Матрица осталась как есть,




и кватернион получился 32767 - 1i + 0j + 0k

И ещё запустим вариант с другими "исходными данными", где картинка повёрнута на 90 градусов:



Матрица в точности та же, что и в прошлый раз, это хорошо.

И кватернион тот же:


23177 + 23165i + 0j + 0k.

Если поделить на 32768 (у нас 32768 соответствует единице), получится

0,7073 + 0,7069i + 0j + 0k

Что-то знакомое - почти что корень из двух на два. Тоже в точности совпадает с прошлым разом.

И ещё один вариант, с поворотом на 180 градусов, для проверки флага знака и чуть другого варианта построения кватерниона (см "Испытываем ABS"):



Да, та же самая матрица.



Тот самый кватернион, строго поворот на 180 градусов.


Ускоренный QuatCore прошёл боевое крещение: правильно посчитал первые 3 в своей жизни кватерниона!
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