nabbla (nabbla1) wrote,
nabbla
nabbla1

Category:

QuatCore начинает фурычить!

Пока что на симуляторе в Quartus'e, но если он там заработал - то высоки шансы, что и на кристалле заработает. Это всё-таки нормальный Timing analysis.

Reset и первые 4 команды - пока всё хорошо :)



Пару слов о программе, которую этот драндулет исполняет. Это первый кусочек аффинного алгоритма, подправленный под наш нынешний набор команд. Сначала приведём сегмент кода:

.code
main proc
            SP          StackAdr
            C           [SP]
            SP          C

            CALL        AffineAlgorithm

@@endless:  JMP         @@endless
main endp

AffineAlgorithm     proc

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

    Compute4PointAffine proc
    Compute4PointAffine endp
    
    FindRoll    proc
    FindRoll    endp
    
    FindScale   proc
    FindScale   endp

    FindVector  proc
    FindVector  endp

            JMP         [--SP]
AffineAlgorithm     endp


Мы начинаем с мучительной инициализации стека. Предположительно, стек мы засунем по такому адресу, к которому не будет "прямого доступа" (это первые 64 и последние 64 слова данных), т.к он и нужен всего один раз, при инициализации. Из-за текущего запрета на операции "из памяти в память", которые распространяются даже на занесение в регистры X/Y/Z/SP значения из памяти (или наоборот), приходится воспользоваться ещё и регистром C из АЛУ. Возможно, в дальнейшем можно будет чуть улучшить модуль QuatCoreMem, но пока попробуем обойтись.

Под спойлером - объявление сегмента данных. Не стал его укорачивать, пущай уж будет "боевым".

[Spoiler (click to open)]
;Бортовая программа ВИПС для QuatCore
;версия от 2.01.2020
;необходимо подрихтовать весь код в соответствии
;с изменившимися командами QuatCore
;и запретом на пересылки "память-память"
;также изменения коснутся представления данных в памяти,
;т.к мы наконец-то созрели до треугольной адресации!

.data

;значения для ZAcc
;возможно, мы решим их переставить местами,
;или раскидать по доступным 128 значениям,
;если это упростит реализацию
ThreeHalf       EQU 0
MinusThreeHalf  EQU 1
RoundZero       EQU 2
Two             EQU 3

ORG     0

;целочисленные координаты на фотопр. матрице
;либо сюда заносится во время захвата,
;либо мы сами задаём на стадии сопровождения
RoughPoints:
RoughX0     Int16   0
RoughY0     Int16   0
RoughX1     Int16   0
RoughY1     Int16   0
RoughX2     Int16   0
RoughY2     Int16   0
RoughX3     Int16   0
RoughY3     Int16   0   ;первые 4

RoughX4     Int16   0
RoughY4     Int16   0
RoughX5     Int16   0
RoughY5     Int16   0
RoughX6     Int16   0
RoughY6     Int16   0
RoughX7     Int16   0
RoughY7     Int16   0   ;следующие 4, для них всех Radius0

RoughX8     Int16   0
RoughY8     Int16   0
RoughX9     Int16   0
RoughY9     Int16   0
RoughX10    Int16   0
RoughY10    Int16   0   ;последние 3, для них задаётся Radius1 
Radius0     Int16   0   ;сюда наш алгоритм помещает для видеопроцессора: какой должен быть радиус "основных" точек (первых 8) и какой радиус последних 3.
Radius1     Int16   0

;сумма X * Pixel[X,Y], Y * Pixel[X,Y], для нахождения ярк. центра
;их выдаёт "видеопроцессор"
;но сейчас имеем дело с уже обработанными - готовыми коорд. ярк центра,
;нули в середине матрицы, 64 отсчёта на пиксель
Points2d:
;дистанция 300 метров, все углы нулевые
Fx0     Int16 53    ;адр 33
Fy0     Int16 -7

Fx1     Int16 480   ;адр 35
Fy1     Int16 -30

Fx2     Int16 -539  ;адр 37
Fy2     Int16 -302

Fx3     Int16 400   ;адр 39
Fy3     Int16 -997

; Fx0       Int16   49
; Fy0       Int16   -5
; Fx1       Int16   479
; Fy1       Int16   -31
; Fx2       Int16   -543
; Fy2       Int16   -304
; Fx3       Int16   398
; Fy3       Int16   -1000

;дистанция 30 метров, поворот 90 градусов
; Fx0       Int16   2996
; Fy0       Int16   4794
; Fx1       Int16   12794
; Fy1       Int16   3974
; Fx2       Int16   2771
; Fy2       Int16   448
; Fx3       Int16   5756
; Fy3       Int16   -5508

;300 метров, ракурс самый мерзопакостный
; Fx0       Int16   425
; Fy0       Int16   22
; Fx1       Int16   85
; Fy1       Int16   -39
; Fx2       Int16   -541
; Fy2       Int16   -301
; Fx3       Int16   285
; Fy3       Int16   -885

Fx4     Int16   -32768  ;адр 38
Fy4     Int16   ?

Fx5     Int16   -32768  ;адр 40
Fy5     Int16   ?

Fx6     Int16   -32768  ;адр 42
Fy6     Int16   ?

Fx7     Int16   -32768  ;адр 44
Fy7     Int16   ?

;Сумма яркостей пикселей для каждого пятна
W0      dw      ?
W1      dw      ?
W2      dw      ?
W3      dw      ?
W4      dw      ?
W5      dw      ?
W6      dw      ?
W7      dw      ?

;адр 30h
.rodata
;константы, которые держатся весь сеанс (если только по МКО не поступил массив полётного задания, который их переопределяет!)

PixToRad dw     27710   ;из пикселей (32768=+512 пикс) в рад (32768=1/4 рад) адр. 30h
MetricW:
ManhW   dw      11010   ;вес, с которым взять Манхэттенскую метрику ;
ChebW   dw      21758   ;вес Чебышевской метрики                    ;
;с такими весами получаем недурственное приближение к Эвклидовой метрике

;заранее посчитанная матрица для нахождения коэф. аффинного преобразования
;МДД3-МДД1-МБД-МДД2
AffineMat:
AfMat00 Int16   4090        ;адр 33h
AfMat01 Int16   10092
AfMat02 Int16   -14492
AfMat03 Int16   310

AfMat10 Int16 -13992        ;адр 37h
AfMat11 Int16 8627
AfMat12 Int16 -2011
AfMat13 Int16 7376

AfMat20 Int16 1199          ;адр 3Bh
AfMat21 Int16 -5752
AfMat22 Int16 -3495
AfMat23 Int16 -5807         ;адр 3Eh
;решили все-все знаки здесь обратить, чтобы не связываться с X<0, который меня уже порядком достал!
;для этого и коэф. нижней строки аф. матрицы обратили, ибо нефиг.

.data
;32 отсчёта дальности, чтобы посчитать скорость сближения сколько-нибудь точно
DistA[0]    dw  0           ;адр. 3Fh
DistA[1]    dw  0
DistA[2]    dw  0
DistA[3]    dw  0
DistA[4]    dw  0
DistA[5]    dw  0
DistA[6]    dw  0
DistA[7]    dw  0
DistA[8]    dw  0
DistA[9]    dw  0
DistA[10]   dw  0
DistA[11]   dw  0
DistA[12]   dw  0
DistA[13]   dw  0
DistA[14]   dw  0
DistA[15]   dw  0
DistA[16]   dw  0
DistA[17]   dw  0
DistA[18]   dw  0
DistA[19]   dw  0
DistA[20]   dw  0
DistA[21]   dw  0
DistA[22]   dw  0
DistA[23]   dw  0
DistA[24]   dw  0
DistA[25]   dw  0
DistA[26]   dw  0
DistA[27]   dw  0
DistA[28]   dw  0
DistA[29]   dw  0
DistA[30]   dw  0
DistA[31]   dw  0       ;адр 5Eh

;стек, решили, наконец-то, что он растёт вверх!
;зарезервируем память для него, адр. 5Fh
Stack   dw  ?   ;1 ячейка для адреса возврата в main
st[1]   dw  ?   ;1 ячейка для адреса возврата из RotateVecByQuat ;адр 5Fh
st[2]   dw  ?   ;для хранения X внутри RotateVecByQuat
st[3]   dw  ?   ;1 ячейка для адреса возврата из QuatMultiply
st[4]   dw  ?   ;для хранения ijk внутри QuatMultiply
st[5]   dw  ?   ;промежут. значение кват (0)
st[6]   dw  ?   ;(1)    
st[7]   dw  ?   ;(2)    
st[8]   dw  ?   ;(3)        ;адр 67

.rodata
ORG 163 ;A3h

;координаты отдельных отражателей мишени ближней дистанции, в увеличенном масштабе
;единица измерения - метры,
;диапазон представимых значений - от -0,125 до примерно +0,125 метров
;пользуемся тем фактом, что ракурс не более чем на 30 градусов, поэтому 
;"есть где развернуться"

MBD1x   Int16   -24904  ;A3h
MBD1y   Int16   22282   ;A4h
MBD1z   Int16   0       ;здесь же MBD2a ;A5h

MBD2x   Int16   -24904  ;A6h
MBD2y   Int16   -22282  ;A7h
MBD2z   Int16   0       ;здесь же MBD3a ;A8h

MBD3x   Int16   0       ;A9h
MBD3y   Int16   28836   ;AAh
MBD3z   Int16   -11796  ;здесь же MBD4a ;ABh

MBD4x   Int16   0       ;ACh
MBD4y   Int16   28836   ;ADh
MBD4z   Int16   13107   ;здесь же MBD5a ;AEh

MBD5x   Int16   0       ;AFh
MBD5y   Int16   8651    ;B0h
MBD5z   Int16   0       ;здесь же MBD6a ;B1h

MBD6x   Int16   0       ;B2h
MBD6y   Int16   -9699   ;B3h
MBD6z   Int16   0       ;здесь же MBD7a ;B4h

MBD7x   Int16   0       ;B5h
MBD7y   Int16   -28836  ;B6h
MBD7z   Int16   -13107  ;здесь же MBD8a ;B7h

MBD8x   Int16   0       ;B8h
MBD8y   Int16   -28836  ;B9h
MBD8z   Int16   13107   ;BAh

;координаты мишеней дальней дистанции (т.е когда смотрим издалека, и отдельные точки сливаются в одну)
;единица измерения - метры, 
;диапазон представимых значений: от -4 до примерно +4 метров
;(хватило бы и -2..+2, но развернуться немножко негде, в прямом смысле)
MDD3x   Int16   0       ;BBh
MDD3y   Int16   -5554   ;BCh
MDD3z   Int16   15794   ;здесь же MDD1a ;BDh

MDD1x   Int16   0       ;BEh
MDD1y   Int16   -6832   ;BFh
ShortRangeRefPoints:    ;и здесь же MDD2a.
MDD1z   Int16   410 ;здесь же MBDa  ;C0h - первый адресуемый по Imm, он же -64

MDD2x   Int16   0       ;C1h
MDD2y   Int16   9339    ;C2h
LongRangeRefPoints:     ;и здесь же MBDa
MDD2z   Int16   4743    ;C3h

MBDx    Int16   -2376   ;адр C4h
MBDy    Int16   0       ;адр C5h
MBDz    Int16   0       ;здесь же MDD2a   адр. C6h
StackAdr    dw  Stack   ;адрес стека (он недоступен напрямую!) C7h

.data
;выходные данные
;"в максимальной комплектации" - ковариационная матрица шума измерений Matrix (комп. a11, a12, a22, и т.д., 21 элем.),
;кватернион взаимной ориентации Quat (QuatA, QuatX, QuatY, QuatZ, 4 слова),
;вектор параллельного переноса (TxOut, Ty, Tz, 3 слова),
;значение скорости (Vel, 1 слово)
;сюда же вклинивается вектор K 1х6 (для алгоритма сопровождения),
;и остаются вакантные места на 6 слов и 5 слов.
;плюс дофига "флагов", которые пока что занимают по 16 бит каждый, но можно будет их и покомпактнее
Matrix:
a11         Int16   ?           ;адр. C8h

a12         Int16   ?
a22         Int16   ?

a13         Int16   ?           ;адр D8h
a23         Int16   ?
a33         Int16   ?

a14         Int16   ?           ;адр E0h
a24         Int16   ?
a34         Int16   ?
a44         Int16   ?

a15         Int16   ?           ;адр E8h
a25         Int16   ?
a35         Int16   ?
a45         Int16   ?
a55         Int16   ?

a16     Int16   ?           ;адр F0h
a26     Int16   ?
a36     Int16   ?
a46     Int16   ?
a56     Int16   ?
a66     Int16   ?   ;всё, этого нам хватит! F5h

state       dw      1   ;0-поиск (подбор экспозиции, грубое определение дистанции), 1-захват, 2-сопровождение
HasData     dw      0   ;0-мы не выдаём данных, 1-выдаём по крайней мере дистанцию и углы с требуемой точностью
QValid      dw      0   ;0-только данные дистанции и 2 углов (кватернион выдаётся, но точность не обеспечивается). 1-точность кватерниона обеспечена
VValid      dw      0   ;0-показания скорости не обеспечивают точности. 1-точность, указанная в ТЗ, обеспечена
Vel         Int16   ?   ;скорость сближения (положительная-отдаляемся, отрицательная-сближаемся, т.е производная от дальности)
ErrCode     dw      0 ;0: всё хорошо, 1: точка, которая ожидалась на экране, при проецировании вышла за пределы (скорее всего, зацепились за блик)
OneHalf     dw      16384 ;для нахождения кватерниона крена. 

K1      Int16   0           ;вектор правой части при решении системы линейных уравнений
K2      Int16   0
K3      Int16   0
K4      Int16   0
K5      Int16   0
K6      Int16   0

TxOut   dw      ?   ;Tx вместе с экспонентой
Exp     dw      ?   ;отдельно экспонента
Tx      dw      ?   ;Tx отдельно
Ty      Int16   ?   ;другие значения
Tz      Int16   ?

QuatA   Int16   ?   ;кватернион взаимной ориентации
QuatX   Int16   ?
QuatY   Int16   ?
QuatZ   Int16   ?

TargetPTR   dw      LongRangeRefPoints  ;когда в дальней зоне, на 3 меньше когда в ближней
TargetCnt   dw      3   ;кол-во мишеней, минус 1: 3 в дальней зоне, 10 в ближней
pad85       dw      ?

;временные переменные. Не знаю, может и в стек их можно было,
;но мы там вызываем другие проц., нужно сдвигать SP,лениво честно говоря :)
AfTransf:
Tx':
Txx     Int16 ?     ;F6h
Ty':
Tyx     Int16 ?     ;F7h
Tz':
Txy     Int16 ?     ;F8h
B0:
Tyy     Int16 ?     ;F9h
Bx:
Rx      Int16 ?     ;FAh
By:
Ry      Int16 ?     ;FBh
Bz      Int16 ?
;коэф. афинного преобр. на этапе захвата
;временная, сдвинутая копия вектора T, если Exp=0..3, на ComputeRoughPoints.
;весь этот бред-чтобы ткнуть носом видеопроцессор "здесь мы ожидаем точку, она нам нахрен не нужна, 
;но не пугайся пожалуйста!"

Local0  Int16   ? ;место для локальной переменной (после вычистки системы команд, мы остались без [SP+2], нужно что-то взамен)
Local1  Int16   ? ;для второй!



Также есть листинг, как оно будет распределено по адресам (результат работы транслятора):

[Spoiler (click to open)]
RoughX0:    00    0
RoughY0:    01    0
RoughX1:    02    0
RoughY1:    03    0
RoughX2:    04    0
RoughY2:    05    0
RoughX3:    06    0
RoughY3:    07    0
RoughX4:    08    0
RoughY4:    09    0
RoughX5:    0A   0
RoughY5:    0B   0
RoughX6:    0C   0
RoughY6:    0D   0
RoughX7:    0E   0
RoughY7:    0F   0
RoughX8:    10   0
RoughY8:    11   0
RoughX9:    12   0
RoughY9:    13   0
RoughX10:   14   0
RoughY10:   15   0
Radius0:    16   0
Radius1:    17   0
Fx0:        18   53
Fy0:        19   65529
Fx1:        1A   480
Fy1:        1B   65506
Fx2:        1C   64997
Fy2:        1D   65234
Fx3:        1E   400
Fy3:        1F   64539
Fx4:        20   32768
Fy4:        21   ????
Fx5:        22   32768
Fy5:        23   ????
Fx6:        24   32768
Fy6:        25   ????
Fx7:        26   32768
Fy7:        27   ????
W0:         28   ????
W1:         29   ????
W2:         2A   ????
W3:         2B   ????
W4:         2C   ????
W5:         2D   ????
W6:         2E   ????
W7:         2F   ????
PixToRad:   30   27710
ManhW:      31   11010
ChebW:      32   21758
AfMat00:    33   4090
AfMat01:    34   10092
AfMat02:    35   51044
AfMat03:    36   310
AfMat10:    37   51544
AfMat11:    38   8627
AfMat12:    39   63525
AfMat13:    3A   7376
AfMat20:    3B   1199
AfMat21:    3C   59784
AfMat22:    3D   62041
AfMat23:    3E   59729
DistA[0]:   3F   0
DistA[1]:   40   0
DistA[2]:   41   0
DistA[3]:   42   0
DistA[4]:   43   0
DistA[5]:   44   0
DistA[6]:   45   0
DistA[7]:   46   0
DistA[8]:   47   0
DistA[9]:   48   0
DistA[10]:  49   0
DistA[11]:  4A   0
DistA[12]:  4B   0
DistA[13]:  4C   0
DistA[14]:  4D   0
DistA[15]:  4E   0
DistA[16]:  4F   0
DistA[17]:  50   0
DistA[18]:  51   0
DistA[19]:  52   0
DistA[20]:  53   0
DistA[21]:  54   0
DistA[22]:  55   0
DistA[23]:  56   0
DistA[24]:  57   0
DistA[25]:  58   0
DistA[26]:  59   0
DistA[27]:  5A   0
DistA[28]:  5B   0
DistA[29]:  5C   0
DistA[30]:  5D   0
DistA[31]:  5E   0
Stack:      5F   ????
st[1]:      60   ????
st[2]:      61   ????
st[3]:      62   ????
st[4]:      63   ????
st[5]:      64  ????
st[6]:      65  ????
st[7]:      66  ????
st[8]:      67  ????
            68  ????
            69  ????
            6A  ????
            6B  ????
            6C  ????
            6D  ????
            6E  ????
            6F  ????
            70  ????
            71  ????
            72  ????
            73  ????
            74  ????
            75  ????
            76  ????
            77  ????
            78  ????
            79  ????
            7A  ????
            7B  ????
            7C  ????
            7D  ????
            7E  ????
            7F  ????
            80  ????
            81  ????
            82  ????
            83  ????
            84  ????
            85  ????
            86  ????
            87  ????
            88  ????
            89  ????
            8A  ????
            8B  ????
            8C  ????
            8D  ????
            8E  ????
            8F  ????
            90  ????
            91  ????
            92  ????
            93  ????
            94  ????
            95  ????
            96  ????
            97  ????
            98  ????
            99  ????
            9A  ????
            9B  ????
            9C  ????
            9D  ????
            9E  ????
            9F  ????
            A0  ????
            A1  ????
            A2  ????
MBD1x:      A3  40632
MBD1y:      A4  22282
MBD1z:      A5  0
MBD2x:      A6  40632
MBD2y:      A7  43254
MBD2z:      A8  0
MBD3x:      A9  0
MBD3y:      AA  28836
MBD3z:      AB  53740
MBD4x:      AC  0
MBD4y:      AD  28836
MBD4z:      AE  13107
MBD5x:      AF  0
MBD5y:      B0  8651
MBD5z:      B1  0
MBD6x:      B2  0
MBD6y:      B3  55837
MBD6z:      B4  0
MBD7x:      B5  0
MBD7y:      B6  36700
MBD7z:      B7  52429
MBD8x:      B8  0
MBD8y:      B9  36700
MBD8z:      BA  13107
MDD3x:      BB  0
MDD3y:      BC  59982
MDD3z:      BD  15794
MDD1x:      BE  0
MDD1y:      BF  58704
MDD1z:      C0  410
MDD2x:      C1  0
MDD2y:      C2  9339
MDD2z:      C3  4743
MBDx:       C4  63160
MBDy:       C5  0
MBDz:       C6  0
StackAdr:   C7  95
a11:        C8  ????
a12:        C9  ????
a22:        CA  ????
a13:        CB  ????
a23:        CC  ????
a33:        CD  ????
a14:        CE  ????
a24:        CF  ????
a34:        D0  ????
a44:        D1  ????
a15:        D2  ????
a25:        D3  ????
a35:        D4  ????
a45:        D5  ????
a55:        D6  ????
a16:        D7  ????
a26:        D8  ????
a36:        D9  ????
a46:        DA  ????
a56:        DB  ????
a66:        DC  ????
state:      DD  1
HasData:    DE  0
QValid:     DF  0
VValid:     E0  0
Vel:        E1  ????
ErrCode:    E2  0
OneHalf:    E3  16384
K1:         E4  0
K2:         E5  0
K3:         E6  0
K4:         E7  0
K5:         E8  0
K6:         E9  0
TxOut:      EA  ????
Exp:        EB  ????
Tx:         EC  ????
Ty:         ED  ????
Tz:         EE  ????
QuatA:      EF  ????
QuatX:      F0  ????
QuatY:      F1  ????
QuatZ:      F2  ????
TargetPTR:  F3  195
TargetCnt:  F4  3
pad85:      F5  ????
Txx:        F6  ????
Tyx:        F7  ????
Txy:        F8  ????
Tyy:        F9  ????
Rx:         FA  ????
Ry:         FB  ????
Bz:         FC  ????
Local0:     FD  ????
Local1:     FE  ????
            FF  ????



Также у нас есть листинг инструкций:
[Spoiler (click to open)]
main proc
00  FD47              SP          StackAdr
01  8AFC              C           [SP]
02  FD83              SP          C
03  F3B0              CALL        AffineAlgorithm
04  B804  @@endless:  JMP         @@endless
main endp
AffineAlgorithm     proc
    Associate4Points    proc
        FindMDD3    proc
05  CD18                      X           Points2D
06  F000                      [SP+1]      0   ;максимальная отдалённость, инициализируем нулём
07  A103                      j           3
08  A003          @@j_loop:   i           3   ;также от 0 до 3, чтобы все расстояния просуммировать
09  FC00                      [SP]        0   ;здесь будет храниться текущий максимум
0A  A201          @@i_loop:   k           1   ;от 0 до 1, т.е значения X и Y
0B  80C9          @@k_loop:   Acc         [X+2i+k]    ;загрузили одно значение
0C  83CA                      SUB         [X+2j+k]    ;вычитаем второе
0D  9C80                      SQRD2       Acc         ;возводим в квадрат
0E  82FC                      ADD         [SP]        ;прибавляем к пред. значению
0F  FC80                      [SP]        Acc
10  AA7B                      kLOOP       @@k_loop        ;теперь то же самое для второй координаты
11  A879                      iLOOP       @@i_loop
12  83F0                      SUB         [SP+1]  ;можно и "пожертвовать" значением в Acc,
13  B004                      JL          @@skip
14  8AFC                      C           [SP]
15  F083                      [SP+1]      C
16  DDA1                      Y           j
17  A971          @@skip:     jLOOP       @@j_loop
18  A0DD                      i           Y
19  A201                      k           1
1A  8AC8          @@swap:     C           [X+k]
1B  80C9                      Acc         [X+2i+k]
1C  C880                      [X+k]       Acc
1D  C983                      [X+2i+k]    C
1E  AA7C                      kLOOP       @@swap  ;а теперь и обе
        FindMDD3    endp
        SortCCW     proc
        SortCCW     endp
    Associate4Points endp
    Compute4PointAffine proc
    Compute4PointAffine endp
    FindRoll    proc
    FindRoll    endp
    FindScale   proc
    FindScale   endp
    FindVector  proc
    FindVector  endp
1F  B8FF              JMP         [--SP]
AffineAlgorithm     endp



Теперь можно отследить, шаг за шагом, что же там происходит.

Первая команда, SP StackAdr (FD 47)
Мы загружаем в указатель стека адрес константы StackAdr. Если глянуть листинг данных, она лежит по адресу C7. Мы же указали в поле SrcAddr число 47. Если мы посмотрим на скриншот, то после сброса (когда сигнал Reset стал низкого уровня), на SrcAddr действительно лежит 47, а на 16-битной шине данных DataBus - значение FFC7. Так происходит из-за расширения знака, который происходит в модуле QuatCoreImm, вот его код:

module QuatCoreIMM (input [7:0] SrcAddr, output [15:0] Q);

assign Q[6:0] = SrcAddr[6:0];
assign Q[15:7] = {9{SrcAddr[6]}}; //sign extension

endmodule


Нам очень хочется уметь представлять маленькие знаковые числа, но на них выделено всего 7 бит в поле команды (первый ноль означает, что мы из 4 модулей мы выбрали QuatCoreIMM, т.е Immediate-значения). Поэтому мы присоединяем к 7-му биту все более старшие, чтобы число -64 осталось таковым и в 16-битной записи.

А дальше происходит ещё одна метаморфоза - модуль памяти сейчас использует 8-битные адреса, поэтому старшие FF начисто игнорируются, и в SP поступает значение C7. Обо всём этом заботится компилятор. Если до значения в памяти можно "достучаться" напрямую, он сформирует правильный адрес, если нет - громко выругается. В этот раз всё пошло как надо.

Теперь смотрим на DestAddr. Как и задумано, там значение FD.
Напомним, что:
адреса 00..7F принадлежат модулю Imm (по Src) / Null (по Dest),
адреса 80..9F принадлежат модулю ALU,
адреса A0..BF принадлежат модулю PC,
адреса C0..FF принадлежат модулю MEM.

И приведём в качестве шпаргалки таблицу адресов MEM:


Адрес FD здесь называется: SP. Всё верно.

Мы видим, что выборка адресов произведена верно, на шине данных лежит то, что надо. Если всё пойдёт правильно, то в SP должно прийти значение C7. На этом такте мы этого узнать не можем, а все-все "потроха" высовывать наружу мне не хотелось. Поехали дальше.

Вторая команда, C [SP] (8A FC)
Видим, что за PC=0 последовало PC=1 (никаких переходов не было). Теперь SrcAddr = FC, DestAddr = 8A - из ПЗУ пришли правильные значения.

На MemAdr по-прежнему сидит значение C7 но теперь оно поступает не с шины данных, а из SP. В ответ на этот адрес, ОЗУ выдаёт значение 005F - адрес, по которому мы хотим разместить стек. Это значение коммутируется на шину данных, и если всё правильно выполнится, должно быть занесено в регистр C а АЛУ. Это операция, выполняющаяся за 1 такт. И действительно, по фронту тактовой частоты PC переключается с 1 на 2. Пока всё хорошо.

Третья команда, SP C (FD 83)
На шине данных по-прежнему значение 005F, но в этот раз поступившее из регистра C. Получателем должен стать регистр SP. Эти 3 команды немного раздражают - будь наши модули чуточку поумнее, можно было бы всё сделать за 1 команду, а может и вовсе научить SP принимать правильное значение по reset'у - и делов с концом! Но пущай будет...

Четвёртая команда, Call AffineAlgorithm, т.е [SP++] Call0 (F3 B0)
А вот это уже куда интереснее!

Модуль PC, при обращении по SrcAddr = B0, должен выдать на шину данных значение PC+1, т.е адрес возврата (по какому адресу надо прыгнуть по выходу из процедуры), и действительно, там мы видим значение 4. В качестве "побочного эффекта" должен произойти прыжок по нулевому адресу из таблицы CallTable. Сейчас компилятор немножечко поумнел и генерит такой код:

//адреса для вызова процедур, "вшитые" в модуль QuatCorePC
module QuatCoreCallTable (input [7:0] SrcAddr, output [4:0] addr);
	assign addr = 
		5'd5;		//AffineAlgorithm
endmodule


А именно, в случае, когда в таблице всего одна запись, она выдаётся "безальтернативно" и должна превратить вход "синхронной загрузки" в обычный "вход установки". Но самое главное - прыжок идёт по адресу 5. И как видно по сигналу PC, так оно и будет.

Теперь смотрим, что происходит на стороне Dest. Адрес возврата мы должны занести в стек. И действительно, в MemAdr поступает адрес 5F, который мы указали как начало стека. По MemContent пока идут нули - все "неинициализированные" области мы всё же инициализировали нулями.

Пока всё идёт как надо. Приведём следующий скриншот:


X Points2D (CD 18)
На шину данных поступает "непосредственное значение" и, вероятно, заносится в регистр X. Скоро проверим...

[SP+1] 0 (F0 00)
Мы "разместили" на стеке две локальные переменные. По адресу [SP] будем хранить текущую сумму, а по [SP+1] - максимальную отдалённости точки до всех остальных. Перед началом цикла заносим туда ноль.

Начало стека у нас было: 5F. Там сейчас лежит адрес возврата, а SP прибавил единичку, став 60. Значит, [SP+1] должен обратиться к адресу в памяти 61. Ага, так и есть! И эта область памяти тоже пока нулевая.

j 3 (A1 03)
На шине данных непосредственное значение 3 - всё верно. Из интересного - в память ОЗУ сформировался адрес 19. В этом нет криминала, и можно расшифровать, что это значит. Когда DestAddr не начинается с двух единиц, QuatCoreMemDecoder считает, что обращение к памяти идёт по SrcAddr. Там у нас значение 00 00 00 11. Старшие 2 бита игнорируются, следующие 2 бита выбирают базовый регистр - X. Следующие 2 бита выбирают второй индекс - это 1. И младшие 2 бита выбирают первый индекс - это 4j. Итого, формируется адрес [X+4j+1], и это действительно обращение по адресу 19, т.е запись в регистр X прошла! Другое дело, значение [X+1] не коммутируется на шину данных - так и должно быть.

К следующему такту мы видим, что действительно j=3. Всё работает.

i 3 (A0 03)
На шине данных значение 3. К следующему такту действительно i=3 - присвоение работает. В модуле памяти по-прежнему формируется адрес [X+4j+1], но теперь, поскольку j=3, вместо 19 получается 25 (это всё hex!), всё верно.

[SP] 0 (FC 00)
Сформировался адрес в ОЗУ 60 - так и надо. Пока содержимое по этому адресу нулевое. Всё верно.

k 1 (A2 01)
На шине данных "непосредственное значение" 1. В модуле MEM "на всякий случай" сформировался адрес [X+2i+1], и действительно, значение в скобках равно 1F.


10 команд, полёт нормальный :)
Продолжение следует. Там начинается работа с АЛУ, и что-то странное происходит, нужно что-то подрихтовать. А вот остальные модули - IMM, MEM и PC - меня пока что радуют, всё чётко :)
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