AlexZabr 0 3 июня, 2007 Опубликовано 3 июня, 2007 · Жалоба После долгих моих тугодумных мук родил 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: Что я в упор не вижу ????? Кроме того, если видите у другие ошибки в коде алгоритма - буду благодарен за указание таковых... P.S. Все переменные в данном asm определены в основном С коде. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
BratherLU 0 4 июня, 2007 Опубликовано 4 июня, 2007 · Жалоба 1 - В mvdd можно использовать только регистры ar2,ar3,ar4,ar5 2 - rnd не стоит использовать т к она работает неправильно читайте эррату на процессор заменить на ADD #1,15,src[,dst] 3 - Загляните в хелп CCS в разделы Register Conventions и Function Conventions Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AlexZabr 0 4 июня, 2007 Опубликовано 4 июня, 2007 · Жалоба 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 ? Нет каких-либо явных ошибок в имплементации алгоритма ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
BratherLU 0 4 июня, 2007 Опубликовано 4 июня, 2007 · Жалоба В 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) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AlexZabr 0 4 июня, 2007 Опубликовано 4 июня, 2007 · Жалоба В 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 и т.д.). Я не прав ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
BratherLU 0 4 июня, 2007 Опубликовано 4 июня, 2007 · Жалоба 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 . Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AlexZabr 0 4 июня, 2007 Опубликовано 4 июня, 2007 · Жалоба 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 данное извне ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
BratherLU 0 4 июня, 2007 Опубликовано 4 июня, 2007 (изменено) · Жалоба ld #0x00,a rpt *(_fir_ord) rptz действительно не принимает indirect addressing только константы на входе - (сорри спутал с rpt) Изменено 4 июня, 2007 пользователем BratherLU Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AlexZabr 0 4 июня, 2007 Опубликовано 4 июня, 2007 · Жалоба 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: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
BratherLU 0 4 июня, 2007 Опубликовано 4 июня, 2007 · Жалоба Коэффициенты тоже должны быть выровнены по соответствующей границе Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AlexZabr 0 4 июня, 2007 Опубликовано 4 июня, 2007 · Жалоба Коэффициенты тоже должны быть выровнены по соответствующей границе Да, так и есть, оба буфера (и коеффициенты и линия задержки выровняны по нужным boundaries (они 150, значит оба буфера выровняны по 256 кратности: один начинается на 0х2000, другой на 0х2100) - это проверено. Это я определил в конфигурации памяти в .cmd (выделил по секции на них, каждая начиная с вышеупомянутых адресов) и соотв. pragmaой в С коде. Так они и сидят. Не понимаю что ему не хватает, все выровняно, вроде правильная индексация в коде, ... :cranky: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
BratherLU 0 4 июня, 2007 Опубликовано 4 июня, 2007 · Жалоба Еще смотрите - что у вас в BK и в ar0 если все ок значит все таки с числом повторений что-то не то если BK=число повторений и ar0=1 (-1), то оба указателя должны вернутся в начало буферов после rpt. Не хочу навязывать свои способы, но попробуйте этот цикл организовать через rptb - сможете отследить промежуточные состояния адресных регистров при расчете выборки и отловить ошибку Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AlexZabr 0 4 июня, 2007 Опубликовано 4 июня, 2007 · Жалоба Еще смотрите - что у вас в BK и в ar0 если все ок значит все таки с числом повторений что-то не то если BK=число повторений и ar0=1 (-1), то оба указателя должны вернутся в начало буферов после rpt. Не хочу навязывать свои способы, но попробуйте этот цикл организовать через rptb - сможете отследить промежуточные состояния адресных регистров при расчете выборки и отловить ошибку Да нет, что-вы, вы ничего не навязываете, ваша помощь очень существенна для новичка типа меня, есть много чему поучиться. :a14: ar0 стабильно держит 1, в BK стабильно сидит загруженное число (150 - порядок фильтра), в BRC стабильно сидит размер буфера входных данных - 1 (буфер у меня 290 samples, в BRC загоняю 289 (0х121)). Хмм, бред какой-то... Кстати, для уточнения: размер линии задержки это порядок фильтра (и кол-во элементов задержки), т.е. для FIRа порядка 150, размер линии задержки (BK) и есть 150, так ? Иногда есть путанница и адже в литературе по DSP длинной фильтра называют то его порядок то кол-во коеффициентов (которое на 1 больше порядка)... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
BratherLU 0 4 июня, 2007 Опубликовано 4 июня, 2007 (изменено) · Жалоба В Данной реализации длина линии задержки==число коэффициентов 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 считает правильно то подав на вход сигнал - дельта функцию (единичный импульс) на выходе получите вектор коэффициентов фильтра Изменено 4 июня, 2007 пользователем BratherLU Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AlexZabr 0 4 июня, 2007 Опубликовано 4 июня, 2007 · Жалоба В Данной реализации длина линии задержки==число коэффициентов 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 системы (которой и являются наши фильтры) даст передаточную функцию системы, то бишь коеффициенты фильтра...хороший способ само-проверки... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться