循環バッファ・アクセス

循環バッファ( Circular Buffer )はFIFO ( First In First Out )構造を実装する方法の一つです。FIFOは名前のとおり最初に入れたデータがあとに入れたデータに押し出されるようなところてん式バッファであり、リアルタイム処理ではちょっとデータを溜め込むためによく使われます。FIFOをプログラムで実装する場合、メモリー上の固定配列をバッファとして使い、FIFOの先頭と末尾を指し示すポインタを組にして実現するのが普通のやり方です。この場合ポインタが配列の上をぐるぐる回ることから循環バッファと呼ばれます。

信号処理では「過去N個のデータ」に対して処理をすることが多くあります。この場合、N+1番目に古いデータは押し出されて捨てられますので、実装はまさに循環バッファで行うことになります。この「過去N個のデータ」に対する処理が余りにも頻繁に現れるため、DSPは循環バッファ・アクセスをオーバーヘッド無しで行うようなアーキテクチャーを持つのが普通です。

ADSP-2191の循環バッファ・アクセスはDAGの中にハードウェアとして実装されています。DAGの8本のインデックス・レジスタIxは16ビットのリニア・アクセス・ポインタですが、Lx、Bxと組み合わせて使うことで循環バッファ・アクセス・モードで使うことができるようになっています。アドレッシングで説明したように、MxレジスタはIxレジスタとの組み合わせを命令で明示的に指定します。これに対してLxとBxはIxと常に暗黙の組み合わせを形成しています。組になるのはxの値が同じレジスタ・セットです。つまり、

という組み合わせです。これはハードウェアで固定しているので変更はできません。

Ixによるアクセスを循環モードにするには、Lxに非0の値を設定します。Lxが0のとき、Ixはリニア・アクセスを行います。LxがNの時、Ixは長さNのバッファを循環アクセスします。ではバッファの先頭はどうやって決めるのでしょうか。バッファの先頭アドレスはBxで指定します。Bxの値は循環アクセスの間不変であり、リニアー・アクセスの時には無視されます。

循環アクセスを開始するとき、Ixの初期値はBxが示すアドレスとBx+Lxが示すアドレスの間になければなりません。

少し例を見てみましょう。下のプログラムはEZ-KIT Liteで動かすことができます。

#include <def219x.h>        // B0 レジスタのマクロ定義をインクルード

.section/dm data1;
.var buf[8];                // バッファを確保。長さは 8
.section/pm program;
.global _main;
.extern _exit;
_main:

        ax0=buf;            // バッファアドレス取得
        reg(B0)=ax0;        // B0 はレジスタ空間にあるので注意
        i0=buf;             // I0 にバッファアドレスを設定
        l0=length(buf);     // L0 にバッファ長を設定
        m0=3;               // 3 ワードおきのアクセス
        ax0=0xa5a5;         // バッファに書き込むデータ

        dm(i0+=m0)=ax0;     // buf[0]
        dm(i0+=m0)=ax0;     // buf[3]
        dm(i0+=m0)=ax0;     // buf[6]
        dm(i0+=m0)=ax0;     // buf[1]   ( 9 を 8 で割った余り )
        dm(i0+=m0)=ax0;     // buf[4]
        dm(i0+=m0)=ax0;     // buf[7]
        dm(i0+=m0)=ax0;     // buf[2]   ( 10 を 8 で割った余り )
        dm(i0+=m0)=ax0;     // buf[6]
        jump    _exit;
 この例では長さ8のバッファを3ごとにアクセスしています。循環バッファの配置は自由です。2の冪の倍数にそろえる必要はありません。B0レジスタはレジスタ空間にマップされているため、専用命令を使ってアクセスします。気をつけてください。

ハードウェアの制限からMxの値はLxより小さなものにしてください。超えた場合どうなるかは未定義です。また、バッファが64KWのページ境界を越えてはいけません。

循環バッファ・モードを使用できるのはPost-Modify with Updateアクセスだけです。この点も注意が必要です。

循環バッファ・モードによるアクセスは、バッファの終端検出オーバーヘッドがまったくありません。この検出は普通にプログラムで実装すると1アクセス毎に実行しなければならないため、畳み込み演算時に耐えられないほど速度が低下します。循環バッファ・モードは本当の意味でDSPに必須の機能なのです。

2191空挺団 | プログラム | EZ-KIT | こぼれ話 | アーキテクチャー | 命令 | レジスタ | DSP掲示板 | FAQ |