реклама на сайте
подробности

 
 
> Нужна помощь разобраться с asm рутиной FIRа, Моя первая самостоятелсьная FIR рутина...
Саша Z
сообщение Jun 3 2007, 18:35
Сообщение #1


Знающий
****

Группа: Свой
Сообщений: 921
Регистрация: 6-04-07
Из: Israel
Пользователь №: 26 822



После долгих моих тугодумных мук родил FIR код в asm который будет част проэкта (вызывается из кода С). Почему-то после добавления ее в проэкт (данного файла asm) - проэкт не компилируется - падает ессно на этой рутине выдавая кучу ошибок. Первая из них весьма странная мне, не могу понять что его не устраивает. Может подскажете чего я не вижу:

Код
.mmregs
.global _p_buffer_in,_p_buffer_out,_dline,_fcoeff,_fir_ord,_p_buff_lenth
.global _fir_processing

_fir_processing:
; saving regs content into stack
    pshm ar0; used as delay line and coeff. cycling addressing increment
    pshm ar1; holds input data array start address
    pshm ar2   ; holds pointer to filter coeff. array addressing
    pshm ar3; holds pointer to delay line array addressing
    pshm ar4; holds output data array start address
    pshm ar5; holds output data array
    nop
    nop
    
; Initialization
    stm #1,ar0                   ;set increment step for cycling buffers
    mvdm *(_fir_ord),BK          ;set cyclic buffer size (for delay line and coeff buffer)
    stm #_p_buff_in,ar1             ;load data_in array start address
    stm #_fcoeff,ar2             ;load coeff. array start address
    stm #_dline,ar3                 ;load delay line array start address
    stm #_p_buffer_out,ar4         ;load output data buffer array address
    mvdm *(_p_buff_length)-1,brc ;load BRC with processing data block length (PROC_BUFFER_LENGTH)
    nop
    nop
    
; Filtration
    rptb fir_loop_end-1            ; repeat FIR routine for entire processing data buffer
    mvdd *ar1+,*ar3+%          ; load next input sample from input proc. array into delay line array
    
    rptz a,_fir_ord-1            ; FIR order less 1 iterations per each input data sample
    mac *ar2+0%,*ar3+0%,a             ; MAC operation on cyclic delay line and coeff. arrays
    
    rnd a                         ; round off value in acc. A to 16 bits
    sth a,*ar4+                      ; store output value into data output array
  fir_loop_end:
    
    popm ar5
    popm ar4
    popm ar3
    popm ar2
    popm ar1
    popm ar0


Первая ошибка которую выдает компилятор:
Цитата
> ERROR ! at line 29: [E0004] Expecting dual memory addressing
mvdd *ar1+, *ar3+%


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

Итак, что ему не нравиться в mvdd ? Она-то вроде перекидывает из памяти в память, и вроде у меня так и есть в коде.... cranky.gif Что я в упор не вижу ?????

Кроме того, если видите у другие ошибки в коде алгоритма - буду благодарен за указание таковых...

P.S. Все переменные в данном asm определены в основном С коде.
Go to the top of the page
 
+Quote Post
3 страниц V   1 2 3 >  
Start new topic
Ответов (1 - 14)
BratherLU
сообщение Jun 4 2007, 05:16
Сообщение #2


Частый гость
**

Группа: Свой
Сообщений: 103
Регистрация: 16-05-06
Пользователь №: 17 126



1 - В mvdd можно использовать только регистры ar2,ar3,ar4,ar5
2 - rnd не стоит использовать т к она работает неправильно читайте эррату на процессор заменить на ADD #1,15,src[,dst]
3 - Загляните в хелп CCS в разделы Register Conventions и Function
Conventions
Go to the top of the page
 
+Quote Post
Саша Z
сообщение Jun 4 2007, 05:59
Сообщение #3


Знающий
****

Группа: Свой
Сообщений: 921
Регистрация: 6-04-07
Из: Israel
Пользователь №: 26 822



Цитата(BratherLU @ Jun 4 2007, 09:16) *
1 - В mvdd можно использовать только регистры ar2,ar3,ar4,ar5
2 - rnd не стоит использовать т к она работает неправильно читайте эррату на процессор заменить на ADD #1,15,src[,dst]
3 - Загляните в хелп CCS в разделы Register Conventions и Function
Conventions


Да, спасибо.
Я вчера рылся в нете насчет инфы по rnd (error подозрительным показался...) и действител-ьно наткнулся на упоминание эрраты, скачал SPRZ 155d - там вторая advisory как раз об этом и говорит. Рекомендуют заменять rnd на то что вы пердложили. Так и сделал в сорсе.
Кстати, вопрос - этот вариант округления результата я видел в примере FIR кода:
http://cnx.org/content/m10023/2.19/, и оттуда его стянул (rnd). Честно говоря не совсем понял резонность такого способа округления до 16 бит. Хелп на rnd говорит о прибавлении к аккумулятору 2^15 степени, затем они там в примере беру как результат старшие 16 бит аккумулятора. е могли бы вы пояснить чайнику каким образом так получаем 16 эффектиных бит (включая знак) ?

Насчет mvdd - понял, спасибо. Загляну в conventions. Пока заменил ее на две инструкции переброски данного через аккумулятор Б.

Еще одна вещь: при прогоне в дебаггере, обнаружил что:
mvdm *(_p_buff_length)-1,brc
не правильно работает - загружает не то значение которое по адресу _p_buff_length. Не знаю почему (может стоит тоже проверить register conventions), но пока заменяю ее на три другие:
ld *(_p_buff_length), b
sub #1, b
stl b, brc
тут загвоздка - в runе, последняя не загружает brc регистр вообще. Наверно применил не ту инструкцию для загрузки mеmory-mapped регистра из аккумулятора. Как правильно это сделать ?

В целом, вам кажется код OK ? Нет каких-либо явных ошибок в имплементации алгоритма ?
Go to the top of the page
 
+Quote Post
BratherLU
сообщение Jun 4 2007, 08:54
Сообщение #4


Частый гость
**

Группа: Свой
Сообщений: 103
Регистрация: 16-05-06
Пользователь №: 17 126



В Conventions описано как праввильно делать вызов асм функций из С, как передать параметры через стэк, и какие регистры использует компилятор для своих нужд (какие регистры требуют сохранения на стэке), а какие можно свободно использовать без сохранения контекста

Код смотрел бегло - то что бросилось в глаза и написал

Да еще при использовании циклической адрессации в mvdd необходимо использовать ar0 для модификации адресных регистров
типа mvdd *ar2+,ar3+0%
Тогда будет работать

mvdm *(_p_buff_length)-1,brc заменить на
mvdk *(_p_buff_length-1),brc

По поводу округления - ссылку не смотрел.
Отвечу опираясь на эррату -
здесь округление до соответствующего 2-чного разряда (младшего значащего в формате Q15 (15 - бит дробная часть 1 бит -3нак)), а не десятичного.
Дорустим:
(АH:AL)=0x00008000 = 0.000015259(=0x8000*(1/0x80000000)) в формате Q31.
Добавляем (единицу сдвинутую на 15)-> AH:AL+0x8000=>
(АH:AL)=0x00008000 =0.000015259(q31)
+ 0x00008000 =0.000015259(q31)
(АH:AL)=0x00010000 = 0.000030517578125(Q31)=0x0001(Q15)
То есть берем старшую часть аккумулятора, а младшую отбрасываем в итоге получается верный 16-битный округленный до ближайшего большего результат в формате (Q15) =0x0001
(PS точка находится между msb msb-1 результата как для Q31 так и для Q15)
Go to the top of the page
 
+Quote Post
Саша Z
сообщение Jun 4 2007, 10:14
Сообщение #5


Знающий
****

Группа: Свой
Сообщений: 921
Регистрация: 6-04-07
Из: Israel
Пользователь №: 26 822



Цитата(BratherLU @ Jun 4 2007, 12:54) *
В Conventions описано как праввильно делать вызов асм функций из С, как передать параметры через стэк, и какие регистры использует компилятор для своих нужд (какие регистры требуют сохранения на стэке), а какие можно свободно использовать без сохранения контекста

Код смотрел бегло - то что бросилось в глаза и написал

Да еще при использовании циклической адрессации в mvdd необходимо использовать ar0 для модификации адресных регистров
типа mvdd *ar2+,ar3+0%
Тогда будет работать

mvdm *(_p_buff_length)-1,brc заменить на
mvdk *(_p_buff_length-1),brc

По поводу округления - ссылку не смотрел.
Отвечу опираясь на эррату -
здесь округление до соответствующего 2-чного разряда (младшего значащего в формате Q15 (15 - бит дробная часть 1 бит -3нак)), а не десятичного.
Дорустим:
(АH:AL)=0x00008000 = 0.000015259(=0x8000*(1/0x80000000)) в формате Q31.
Добавляем (единицу сдвинутую на 15)-> AH:AL+0x8000=>
(АH:AL)=0x00008000 =0.000015259(q31)
+ 0x00008000 =0.000015259(q31)
(АH:AL)=0x00010000 = 0.000030517578125(Q31)=0x0001(Q15)
То есть берем старшую часть аккумулятора, а младшую отбрасываем в итоге получается верный 16-битный округленный до ближайшего большего результат в формате (Q15) =0x0001
(PS точка находится между msb msb-1 результата как для Q31 так и для Q15)



OK, спасибо но заменив на mvdk *(_p_buff_length-1),brc ничего не дало, работает так-же ошибочно как и с mvdm (т.е. загружается в BRC ошибочная переменная и единица не вычитается)..
Странно..пока заменил 4мя другими коммандами чтоб работало:
Код
.bss temp, 1
.
.
ld *(_pbuff_length), b
sub #1, b
stl, b, *(temp)
mvdm *(temp), brc

не эффективно, но работает...

вернул обратно mvdd *ar2+,ar3+0% (в ar2 -> pointer на массив данных, ar3 -> pointer на линию задержки = 150) - приняло.
Но в дебаггере при runе, вследствии поядка следваания комманд:
Код
mvdd *ar1+,*ar3+%         ; load next input sample from input proc. array into delay line array
rptz a,_fir_ord-1                ; FIR order less 1 iterations per each input data sample
mac *ar2+0%,*ar3+0%,a  ; MAC operation on cyclic delay line and coeff. array

наблюдаю что указатель на линию задержки (в ar3) после каждого люпа (150 итераций) прыгает через 6 адресов (т.в. если первый sample из массива данных он положил по первому адресу линии задержки: 0х2000, то после люпа, след. sample он ложит в 0х2007).
Мне казалось что должна происходить циркуляция по заданному циклу (150), т.е. каждый послед. sample из массива данных должен ложиться в послед. адрес линии задержки (0х2000 -> 0х2001 -> 0х2003 и т.д.). Я не прав ?
Go to the top of the page
 
+Quote Post
BratherLU
сообщение Jun 4 2007, 11:06
Сообщение #6


Частый гость
**

Группа: Свой
Сообщений: 103
Регистрация: 16-05-06
Пользователь №: 17 126



mvdk *(_p_buff_length-1),brc сорри Вас запутал и сам заплутал
mvdk *(_p_buff_length-1),brc - такая штука загрузит в брс значение из ячейки с абсолютным адресом (_p_buff_length-1).

Поэтому - по адресу _p_buff_length должно лежать сразу нужное значение (на единицу меньше), если хотите использовать
mvdk *(_p_buff_length),brc

По поводу циркулярной адрессации и rptz грабли таки
rptz a,_fir_ord-1 , если _fir_ord - адрес внешней константы (в сях), то компилер реально считает, что число повторений следующей инструкции лежит по адресу _fir_ord-1 и выполняет инструкцию это число раз +1 - ничего общего с Вашей задумкой я думаю
=> два способа вызова rptz (Mnemonic insruction Set)
1 rptz a,#_fir_ord-1
повторит след инструкция _fir_ord раз, где _fir_ord - константа объявленная в этом же асме или еще где во внешнем асме чере .set
2 rptz a,*(_fir_ord)
в этом случае повторит след инструкция число раз +1 лежащих по адрес _fir_ord .
Go to the top of the page
 
+Quote Post
Саша Z
сообщение Jun 4 2007, 11:27
Сообщение #7


Знающий
****

Группа: Свой
Сообщений: 921
Регистрация: 6-04-07
Из: Israel
Пользователь №: 26 822



Цитата(BratherLU @ Jun 4 2007, 15:06) *
mvdk *(_p_buff_length-1),brc сорри Вас запутал и сам заплутал
mvdk *(_p_buff_length-1),brc - такая штука загрузит в брс значение из ячейки с абсолютным адресом (_p_buff_length-1).

Поэтому - по адресу _p_buff_length должно лежать сразу нужное значение (на единицу меньше), если хотите использовать
mvdk *(_p_buff_length),brc

По поводу циркулярной адрессации и rptz грабли таки
rptz a,_fir_ord-1 , если _fir_ord - адрес внешней константы (в сях), то компилер реально считает, что число повторений следующей инструкции лежит по адресу _fir_ord-1 и выполняет инструкцию это число раз +1 - ничего общего с Вашей задумкой я думаю
=> два способа вызова rptz (Mnemonic insruction Set)
1 rptz a,#_fir_ord-1
повторит след инструкция _fir_ord раз, где _fir_ord - константа объявленная в этом же асме или еще где во внешнем асме чере .set
2 rptz a,*(_fir_ord)
в этом случае повторит след инструкция число раз +1 лежащих по адрес _fir_ord .


Спасибо, понял.
Пробую: rptz a, *(_fir_ord) не проходит компиляцию - компайлер выдает ошибку утверждая что rptz не принимает indirect addressing.

У меня, все глобальные констатнты и определения (включая -fir_ord) определены через главный С файл, посему действительно как вы и говорите нужно indirectt addressing, но засада видимо в том что комманда rptz не принимает indirect.
Неужели нет выхода и нужно в asm коде определять временную переменную и в нее кидать значение _fir_ord данное извне ?
Go to the top of the page
 
+Quote Post
BratherLU
сообщение Jun 4 2007, 11:58
Сообщение #8


Частый гость
**

Группа: Свой
Сообщений: 103
Регистрация: 16-05-06
Пользователь №: 17 126



ld #0x00,a
rpt *(_fir_ord)

rptz действительно не принимает indirect addressing только константы на входе - (сорри спутал с rpt)

Сообщение отредактировал BratherLU - Jun 4 2007, 11:49
Go to the top of the page
 
+Quote Post
Саша Z
сообщение Jun 4 2007, 12:03
Сообщение #9


Знающий
****

Группа: Свой
Сообщений: 921
Регистрация: 6-04-07
Из: Israel
Пользователь №: 26 822



Цитата(BratherLU @ Jun 4 2007, 15:46) *
ld #0x00,a
rpt *(_fir_ord)


ОК, уже скомпилировалось, но при прогоне ар3 адресация (т.е. pointer в линии задержки) прыгает через один адрес при его загрузке (загрузке очередного sample сигнала). Странно, неужели опять не то число циркуляций ?

С дургой стороны, заменил ради интереса rptz a, *(_fir_ord) (который не компилировался) на прямое:
rptz a, #150-1 (150 - порядок фильтра) - тогда загрузка в линию задержки в цикле шла нормально, но зато в mac *ar4+0%, *ar3+0%, a поинтер в ar4 (буфер коэффициентов) прыгал меду началом и след. адресом, туда - обратно и не продвигался дальше по буферу. Чего-то я теряю нить... cranky.gif
Go to the top of the page
 
+Quote Post
BratherLU
сообщение Jun 4 2007, 12:07
Сообщение #10


Частый гость
**

Группа: Свой
Сообщений: 103
Регистрация: 16-05-06
Пользователь №: 17 126



Коэффициенты тоже должны быть выровнены по соответствующей границе
Go to the top of the page
 
+Quote Post
Саша Z
сообщение Jun 4 2007, 12:28
Сообщение #11


Знающий
****

Группа: Свой
Сообщений: 921
Регистрация: 6-04-07
Из: Israel
Пользователь №: 26 822



Цитата(BratherLU @ Jun 4 2007, 16:07) *
Коэффициенты тоже должны быть выровнены по соответствующей границе


Да, так и есть, оба буфера (и коеффициенты и линия задержки выровняны по нужным boundaries (они 150, значит оба буфера выровняны по 256 кратности: один начинается на 0х2000, другой на 0х2100) - это проверено. Это я определил в конфигурации памяти в .cmd (выделил по секции на них, каждая начиная с вышеупомянутых адресов) и соотв. pragmaой в С коде. Так они и сидят.
Не понимаю что ему не хватает, все выровняно, вроде правильная индексация в коде, ... cranky.gif
Go to the top of the page
 
+Quote Post
BratherLU
сообщение Jun 4 2007, 12:43
Сообщение #12


Частый гость
**

Группа: Свой
Сообщений: 103
Регистрация: 16-05-06
Пользователь №: 17 126



Еще смотрите - что у вас в BK и в ar0 если все ок значит все таки с числом повторений что-то не то
если BK=число повторений и ar0=1 (-1), то оба указателя должны вернутся в начало буферов после rpt. Не хочу навязывать свои способы, но попробуйте этот цикл организовать через rptb - сможете отследить промежуточные состояния адресных регистров при расчете выборки и отловить ошибку
Go to the top of the page
 
+Quote Post
Саша Z
сообщение Jun 4 2007, 13:07
Сообщение #13


Знающий
****

Группа: Свой
Сообщений: 921
Регистрация: 6-04-07
Из: Israel
Пользователь №: 26 822



Цитата(BratherLU @ Jun 4 2007, 16:43) *
Еще смотрите - что у вас в BK и в ar0 если все ок значит все таки с числом повторений что-то не то
если BK=число повторений и ar0=1 (-1), то оба указателя должны вернутся в начало буферов после rpt. Не хочу навязывать свои способы, но попробуйте этот цикл организовать через rptb - сможете отследить промежуточные состояния адресных регистров при расчете выборки и отловить ошибку


Да нет, что-вы, вы ничего не навязываете, ваша помощь очень существенна для новичка типа меня, есть много чему поучиться. a14.gif

ar0 стабильно держит 1, в BK стабильно сидит загруженное число (150 - порядок фильтра), в BRC стабильно сидит размер буфера входных данных - 1 (буфер у меня 290 samples, в BRC загоняю 289 (0х121)). Хмм, бред какой-то...

Кстати, для уточнения: размер линии задержки это порядок фильтра (и кол-во элементов задержки), т.е. для FIRа порядка 150, размер линии задержки (BK) и есть 150, так ? Иногда есть путанница и адже в литературе по DSP длинной фильтра называют то его порядок то кол-во коеффициентов (которое на 1 больше порядка)...
Go to the top of the page
 
+Quote Post
BratherLU
сообщение Jun 4 2007, 14:13
Сообщение #14


Частый гость
**

Группа: Свой
Сообщений: 103
Регистрация: 16-05-06
Пользователь №: 17 126



В Данной реализации длина линии задержки==число коэффициентов FIR
А так совет пусть не эффективно но наглядно
- отлаживайтесь по частям - добейтесь, чтоб после обсчета ОДНОЙ выборки у Вас указатели внутри буферов оказались там где должны оказаться раз уж взялись за циклическую адрессацию.
Ну типа ->
...
инициализация ar3,ar4,
...
stm #1,ar0
stm #(число коэффициентов FIR),bk
stm #(число коэффициентов FIR -1),brc
ld #0x00,a
nop
nop
...
;//(подгружаем отсчет в линию задержки)
ld #0x00,a
rptb _loop_end-1
mac *ar4+0%,*ar3+0%,a
_loop_end
;//(указатели ar4, ar3 при таком контексте будет такими же как и до rptb)
...
и т.д.
Смотрите в симуляторе как где и что меняется и где заканчивается.
Заведется это - перепишите уже как Вам нравится с использованием rpt внутри и rptb снаружи
На перед скажу, если Ваш FIR считает правильно то подав на вход сигнал - дельта функцию (единичный импульс) на выходе получите вектор коэффициентов фильтра

Сообщение отредактировал BratherLU - Jun 4 2007, 14:17
Go to the top of the page
 
+Quote Post
Саша Z
сообщение Jun 4 2007, 18:18
Сообщение #15


Знающий
****

Группа: Свой
Сообщений: 921
Регистрация: 6-04-07
Из: Israel
Пользователь №: 26 822



Цитата(BratherLU @ Jun 4 2007, 18:13) *
В Данной реализации длина линии задержки==число коэффициентов FIR
А так совет пусть не эффективно но наглядно
- отлаживайтесь по частям - добейтесь, чтоб после обсчета ОДНОЙ выборки у Вас указатели внутри буферов оказались там где должны оказаться раз уж взялись за циклическую адрессацию.
Ну типа ->
...
инициализация ar3,ar4,
...
stm #1,ar0
stm #(число коэффициентов FIR),bk
stm #(число коэффициентов FIR -1),brc
ld #0x00,a
nop
nop
...
;//(подгружаем отсчет в линию задержки)
ld #0x00,a
rptb _loop_end-1
mac *ar4+0%,*ar3+0%,a
_loop_end
;//(указатели ar4, ar3 при таком контексте будет такими же как и до rptb)
...
и т.д.
Смотрите в симуляторе как где и что меняется и где заканчивается.
Заведется это - перепишите уже как Вам нравится с использованием rpt внутри и rptb снаружи
На перед скажу, если Ваш FIR считает правильно то подав на вход сигнал - дельта функцию (единичный импульс) на выходе получите вектор коэффициентов фильтра



Да, спасибо, так и сделал (проверочную рутину с rptb). по выходу из цикла (_loop_end), ar4 (коефф.) действительно вернулся на начало (0х2100) а вот ar3 (линия задержки) оказалась на 0х2001, т.е. ушла на 1 вперед (ее начало в 0х2000). Но в приципе это кажется логично ибо изначально указатель линии задержки инкрементировался до входа в цикл (mvdd *ar1+,*ar3+%), т.е. он по идее опережает инкремент коеффициентов на 1. Вроде все логично, так ?
Если это правильно - верну обратно "оперативный" вариант и проверю еще раз...

Насчет проверки рутины подачей импульса - это вы правы, импульс на входе LTI системы (которой и являются наши фильтры) даст передаточную функцию системы, то бишь коеффициенты фильтра...хороший способ само-проверки...
Go to the top of the page
 
+Quote Post

3 страниц V   1 2 3 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 19th July 2025 - 09:32
Рейтинг@Mail.ru


Страница сгенерированна за 0.01504 секунд с 7
ELECTRONIX ©2004-2016