int型FIRディジタルフィルタプログラム

Copyright (C) 17Feb2004 coskx

【1】int型FIRディジタルフィルタプログラム

SH2はint型積和演算する命令と専用レジスタを持っている。ここではSH2のint型積和演算する命令と専用レジスタを用いたint型FIRディジタルフィルタプログラムについて解説する。(SH2DSPはFIRディジタルフィルタ演算専用の命令ももっているようである。)FIRディジタルフィルタに関してはここでは解説しない。

ファイルのダウンロード

DownLoad

【2】int型FIRディジタルフィルタのCプログラム(PC上などで動作)

ポインタとリングバッファを使用したint型FIRディジタルフィルタは,Cでは次の例のように作成できる。テスト用メインではインパルスレスポンスを計算している。(係数列がそのまま出力される。)

Cプログラミング(tap長5のFIRディジタルフィルタ)

#include <stdio.h>
#define SIZE 5

short int coef[SIZE];
short int rngbuff[SIZE];
short int *prngendm1;
short int *prngend;

/*フィルタ演算*/
short int digitalfilter(short int data)
{
    static short int *pcurrent=rngbuff;
    short int y=0;
    short int *prngbuff;
    short int *pcoef=coef;
    *pcurrent=data;
    prngbuff=pcurrent;
    do {
        y+=(*(pcoef++))*(*(prngbuff++));
    } while (prngbuff!=prngend);
    prngbuff=rngbuff;
    while (prngbuff!=pcurrent) {
        y+=(*(pcoef++))*(*(prngbuff++));
    }
    if (pcurrent!=rngbuff) pcurrent--;
    else pcurrent=prngendm1;
    return y;
}

/*係数列のセット*/
void setCoeff(short int c[],int number)
{
    int i;
    for (i=0; i<number; i++) coef[i]=c[i];
    for (   ; i<SIZE; i++)   coef[i]=0;
}

/*バッファの初期化*/
void clearbuff(int number)
{
    int i;
    for (i=0; i<number; i++) rngbuff[i]=0;
    prngendm1=rngbuff+number-1;
    prngend=rngbuff+number;
}

int main(void)
{
    short int cc[SIZE];
    short int x,y;
    int i;
    for (i=0; i<SIZE; i++) cc[i]=i*10;
    setCoeff(cc,SIZE);
    clearbuff(SIZE);
    for (i=0; i<SIZE*2; i++) {
        if (i%SIZE==0) y=digitalfilter(1);
        else y=digitalfilter(0);
        printf("%d %d\n",i,y);
    }
}

実行結果
0 0
1 10
2 20
3 30
4 40
5 0
6 10
7 20
8 30
9 40

【3】int型FIRディジタルフィルタのCプログラム(SH2などで動作)

Cプログラミング(tap長5のFIRディジタルフィルタ)

#include "7040S.H"
#include "sh_7045.h"

#define SIZE 5

short int coef[SIZE];
short int rngbuff[SIZE];
short int *prngendm1;
short int *prngend;

short int digitalfilter(short int data)
{
    static short int *pcurrent=rngbuff;
    short int y=0;
    short int *prngbuff;
    short int *pcoef=coef;
    *pcurrent=data;
    prngbuff=pcurrent;
    do {
        y+=(*(pcoef++))*(*(prngbuff++));
    } while (prngbuff!=prngend);
    prngbuff=rngbuff;
    while (prngbuff!=pcurrent) {
        y+=(*(pcoef++))*(*(prngbuff++));
    }
    if (pcurrent!=rngbuff) pcurrent--;
    else pcurrent=prngendm1;
    return y;
}

void setCoeff(short int c[],int number)
{
    int i;
    for (i=0; i<number; i++) coef[i]=c[i];
    for (   ; i<SIZE; i++)   coef[i]=0;
}

void clearbuff(int number)
{
    int i;
    for (i=0; i<number; i++) rngbuff[i]=0;
    prngendm1=rngbuff+number-1;
    prngend=rngbuff+number;
}

int main(void)
{
    short int cc[SIZE];
    short int x,y;
    int i;
    initSCI1();
    for (i=0; i<SIZE; i++) cc[i]=i*10;
    setCoeff(cc,SIZE);
    clearbuff(SIZE);
    for (i=0; i<SIZE*2; i++) {
        if (i%SIZE==0) y=digitalfilter(1);
        else y=digitalfilter(0);
        SCI1_printf("%d %d\n",i,y);
    }
}

実行結果
0 0
1 10
2 20
3 30
4 40
5 0
6 10
7 20
8 30
9 40

【4】int型FIRディジタルフィルタのアセンブリプログラム(SH2などで動作 ディジタルフィルタ演算部をセンブリ言語で記述)

ここではint型FIRディジタルフィルタ演算に積和機能を利用した。
mac.w   @r3+, @r7+」はr3とr7の内容をアドレスとするwordの積を作り,macに加え,r3とr7を1word分(=2)増加させる。

Cプログラミング(tap長5のFIRディジタルフィルタ)

#include "7040S.H"
#include "sh_7045.h"

#define SIZE 5

short int coef[SIZE];
short int rngbuff[SIZE];
short int *prngendm1;
short int *prngend;

short int digitalfilter(short int data);

void setCoeff(short int c[],int number)
{
    int i;
    for (i=0; i<number; i++) coef[i]=c[i];
    for (   ; i<SIZE; i++)   coef[i]=0;
}

void clearbuff(int number)
{
    int i;
    for (i=0; i<number; i++) rngbuff[i]=0;
    prngendm1=rngbuff+number-1;
    prngend=rngbuff+number;
}

int main(void)
{
    short int cc[SIZE];
    short int x,y;
    int i;
    initSCI1();
    for (i=0; i<SIZE; i++) cc[i]=i*10;
    setCoeff(cc,SIZE);
    clearbuff(SIZE);
    for (i=0; i<SIZE*2; i++) {
        if (i%SIZE==0) y=digitalfilter(1);
        else y=digitalfilter(0);
        SCI1_printf("%d %d\n",i,y);
    }
}

アセンブリフィルタリング関数

    .global _rngbuff
    .global _prngend
    .global _coef
    .global _prngendm1
/********************************************************************/
    .data
    .align 2
_pcurrent.0:
    .long _rngbuff
    .text
    .align 4
    .global _digitalfilter
_digitalfilter:
    /* *pcurrent=data;     */
    /* prngbuff=pcurrent;  */
    mov.l   addressof_pcurrent,r2     /* r2 : pcurrentのアドレス */
    mov.l   @r2,r3                    /* r3 : ポインタprngbuff   */
    mov.w   r4,@r3                    /* r4 : arg1(data)であった 使用済 */

    /* y=0;                                     */
    /* do {                                     */
    /*     y+=(*(pcoef++))*(*(prngbuff++));     */
    /* } while (prngbuff!=prngend);             */
    mov.l   addressof_prngend,r1      /* r1 : prngendのアドレス */
    mov.l   addressof_coef,r7         /* r7 : ポインタpcoef      */
    mov.l   @r1,r6                    /* r6 : prngend ループ終了チェック用  */
    clrmac                            /*MACレジスタ(積和レジスタ)の初期化*/
L2:
    mac.w   @r3+, @r7+
    cmp/eq  r6,r3
    bf.s    L2
    nop

    /* prngbuff=rngbuff;  */
    mov.l   addressof_rngbuff,r3      /* r3 : prngbuff rngbuff先頭アドレス */

    /* while (prngbuff!=pcurrent) {                */
    /*     y+=(*(pcoef++))*(*(prngbuff++));        */
    /* }                                           */
    mov.l   @r2,r6                    /* r6 : pcurrent ループ終了チェック用 */
    cmp/eq  r3,r6
    bt.s    L23
    mov     r3,r5                      /* r5 : rngbuffの先頭アドレス */

L9:
    mac.w   @r3+, @r7+
    cmp/eq  r6,r3
    bf.s    L9
    nop

    /* if (pcurrent!=rngbuff) pcurrent--;      */
    /* else pcurrent=prngendm1;                */
    /* return y;                               */
    cmp/eq  r5,r6
L23:
    bt      L10
    add     #-2,r6
    mov.l   r6,@r2
L11:
    rts
    sts     macl, r0     /*結果をR0 に得る*/
L10:
    mov.l    addressof_prngendm1,r1
    mov.l    @r1,r0
    bra      L11
    mov.l    r0,@r2
L21:
    .align 2
addressof_pcurrent:
    .long _pcurrent.0
addressof_prngend:
    .long _prngend
addressof_coef:
    .long _coef
addressof_rngbuff:
    .long _rngbuff
addressof_prngendm1:
    .long _prngendm1
/********************************************************************/
    .end

実行結果
0 0
1 10
2 20
3 30
4 40
5 0
6 10
7 20
8 30
9 40

 

【5】性能測定
「【3】,【4】」のプログラムを一部変更して,演算時間の測定を行なった。

変更箇所
#define SIZE 256
int main(void)
{
    short int cc[SIZE];
    short int x,y;
    long int i;
    initSCI1();
    for (i=0; i<SIZE; i++) cc[i]=i;
    setCoeff(cc,SIZE);
    clearbuff(SIZE);
    for (i=0; i<1000000; i++) {
        if ((i&0xff)==0) {
            y=digitalfilter(1);
            SCI1_printf("%d %d\n",i,y);
        } else {
            y=digitalfilter(0);
        }
        /*SCI1_printf("%d %d\n",i,y);*/
    }
}

測定結果

プログラム

演算性能

【3】Cで記述したフィルタ 10秒間に256tapのFIRディジタルフィルタリングを75000回程度実行
【4】積和機能を利用したアセンブリ言語記述のフィルタ 10秒間に256tapのFIRディジタルフィルタリングを107000回程度実行

 

【6】int型FIRディジタルフィルタのアセンブリプログラム(SH2などで動作 ディジタルフィルタ演算部をセンブリ言語でループなし記述)

ここではint型FIRディジタルフィルタ演算に積和機能を利用し,ループを用いずに直接tapの数だけ演算命令を羅列。
そのため,tap係数長を変更するには直接アセンブリプログラムを変更しなければばらない。

Cプログラミング(tap長256のFIRディジタルフィルタ)

#include "7040S.H"
#include "sh_7045.h"

#define SIZE 256

short int coef[SIZE];
short int rngbuff[SIZE*2];

short int digitalfilter(short int data);

void setCoeff(short int c[],int number)
{
    int i;
    for (i=0; i<number; i++) coef[i]=c[i];
    for (   ; i<SIZE; i++)   coef[i]=0;
}

void clearbuff(int number)
{
    int i;
    for (i=0; i<number*2; i++) rngbuff[i]=0;
}

int main(void)
{
    short int cc[SIZE];
    short int x,y;
    long int i;
    initSCI1();
    for (i=0; i<SIZE; i++) cc[i]=(i-(SIZE>>1));
    setCoeff(cc,SIZE);
    clearbuff(SIZE);
    for (i=0; i<1000000; i++) {
        if ((i&0xff)==0) {
            y=digitalfilter(1);
            SCI1_printf("%d %d\n",i,y);
        } else {
            y=digitalfilter(0);
        }
        /*SCI1_printf("%d %d\n",i,y);*/
    }
}

アセンブリフィルタリング関数

    .global _rngbuff
    .global _coef
/********************************************************************/
    .data
    .align 2
_pcurrent1.0:
    .long _rngbuff
    .align 2
_pcurrent2.1:
    .long _rngbuff+512         /*SIZE*2=512*/
    .text
    .align 1
    .align 4
    .global _digitalfilter
_digitalfilter:
    mov.l r8,@-r15
    exts.w r4,r4
    mov.l L18,r8         /*ポインタ_pcurrent2.1のアドレス*/
    mov #0,r0              /*y=0*/
    mov.l r14,@-r15
    mov.l @r8,r1         /*ポインタ_pcurrent2.1*/
    mov r15,r14
    mov.l L19,r5         /*ポインタ_pcurrent1.0のアドレス*/
    mov r1,r3
    mov.l @r5,r2         /*ポインタ_pcurrent1.0*/
    mov.w r4,@r1         /*r4(data)をポインタ_pcurrent2.1の指すところへ*/
    cmp/hi r2,r1
    mov.l L16,r6         /*coefの先頭アドレス*/
    bf.s L2
    mov.w r4,@r2         /*r4(data)をポインタ_pcurrent1.0の指すところへ*/
    mov r2,r3
L2:
                           /*ここまでにr3がprngbuffになっている*/

    clrmac                    /*MACレジスタの初期化*/
    /*256回の積和演算をループではなく直接記述*/
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+

    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+

    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+

    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+

    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+

    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+

    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+

    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+

    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+

    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+

    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+

    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+

    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+

    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+

    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+

    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+
    mac.w    @r3+, @r6+

    sts      macl, r0           /*結果をR0 に得る*/

    mov.l @r5,r1
    mov.l L17,r3           /*_rngbuffの先頭アドレス*/
    cmp/eq r3,r1
    bt.s L8
    add #-2,r1
    mov.l r1,@r5
L9:
    mov.l @r8,r1
    cmp/eq r3,r1
    bt L10
    add #-2,r1
    mov.l r1,@r8
L11:
    mov r14,r15
    mov.l @r15+,r14
    rts 
    mov.l @r15+,r8
    .align 4
L10:
    mov r1,r2
    mov.l L18,r1
    mov.l TAILOFFSET,r4
    add r4,r2
    bra L11
    mov.l r2,@r1
    .align 4
L8:
    mov r3,r2
    mov.l L19,r1
    mov.l TAILOFFSET,r4
    add r4,r2
    bra L9
    mov.l r2,@r1
L20:
    .align 2
L18:
    .long _pcurrent2.1
L19:
    .long _pcurrent1.0
L16:
    .long _coef
L17:
    .long _rngbuff
TAILOFFSET:
    .long 1022               /*SIZE*2*2-2=1022*/
/********************************************************************/
    .end

 

測定結果

プログラム

演算性能

【3】Cで記述したフィルタ 10秒間に256tapのFIRディジタルフィルタリングを75000回程度実行
【4】積和機能を利用したアセンブリ言語記述のフィルタ 10秒間に256tapのFIRディジタルフィルタリングを107000回程度実行
【6】積和機能を直列利用したアセンブリ言語記述のフィルタ 10秒間に256tapのFIRディジタルフィルタリングを187000回程度実行