dsPIC33FJ64GP802 (3) --- DSP 命令と DSP ライブラリ (1)

 FIR (Finite Impulse Response) フィルタの計算では、FIR フィルタの「タップ」ひとつあたり 1 回の積和演算が必要です。
 積和の乗算ではオペランドを 2 つ必要とするので、メモリ・アクセスが 2 回必要となります。
 したがって、タップひとつ分の計算を 1 サイクルで実行するためには、ふたつのオペランドのフェッチをそれぞれ別のデータバスを介して同時に行うか、あるいは、2 つのオペランドがひとつのワードに「パック」されたデータを単一のデータバスから読み出す必要があります。
 積和演算などの「DSP 命令セット」を持つプロセッサは多いのですが、データバスが 2 重化されているものは少なく、タップひとつあたり 2 命令以上を必要とする場合が多いです。
 dsPIC の場合には、X-バスと Y-バスの 2 系統のデータバスを備えており、タップひとつあたり 1 命令、1 サイクルで実行できます。
 単に DSP 命令を追加しましたというレベルにとどまらず、古典的な固定小数点演算の専用 DSP に匹敵するアーキテクチャとなっています。
 しかし、クロックが最大 40 MHz と遅いので、タップひとつあたり 2 サイクル以上かかる他の高速クロックのプロセッサにトータルでは負ける場合があります。
 ペリフェラルなどがぶら下がっている、通常の命令でも使われるデータバスが X-バスと呼ばれていて、Y-バスは DSP 演算専用になっています。
 乗算は「可換」ですから、「遅延要素」と「フィルタ係数」とを、どちらのバスに割り当てるかは任意ですが、後述する DSP ライブラリ関数では、遅延要素を Y-バスに、係数を X-バスあるいはプログラム・メモリに割り当てています。
 これは、遅延要素へは読み書きを行うのに対し、可変フィルタではないフィルタの場合、係数は通常は「定数」なので、読み取り専用のプログラム・メモリ上に置いて利用できることが関係していると思われます。
 dsPIC には「PSV」(Program Space Visibility Operation) という機能があって、プログラム・メモリ上の内容を X-バスの特定領域にマッピングして、読み取り専用データとしてアクセスすることができます。
 フィルタ係数を直接 X-バスに置く場合と、PSV を利用してプログラム・メモリに置く場合では、ライブラリ関数の実行時間に差が生じるので、ドキュメントではそれぞれの場合について実行時間の計算式が示されています。
 積和命令 (Multiply and Accumulate) のアセンブリ命令は、たとえば次のようになります。

MAC W6*W7, B, [W8]+=2, W6, [W10]-=6, W7, [W13]+=2

 dsPIC では「ワーキング・レジスタ」として、W0 から W15 までの 16 本の 16 ビット・レジスタがあり、データ・レジスタあるいはアドレス・レジスタとして使用できます。
 アキュムレータは A、B の 2 本あり、40 ビット幅となっています。
 MAC 命令の乗算のオペランドとしては、W4 ~ W7 の 4 本のレジスタが使えます。
 上の命令の「W6*W7, B」の部分は
(W6 * W7) → Acc B
つまり、(すでにデータが格納されている) W6 と W7 の内容を乗算し、アキュムレータ B に累加することを指定しています。
 2 番目の「[W8]+=2, W6」の部分は、アドレス・レジスタとして W8 を使い、X-バスから 16 ビット・データを読み出し、W6 に格納し、W8 を 2 だけポスト・インクリメントすることを指定しています。
 読み出したデータが利用可能になるのは、次の命令の実行時になります。
 この X-バスのアドレス・レジスタとして W8 あるいは W9 を指定できます。
 ポスト・インクリメント (デクリメント) 量として、
-6, -4, -2, 2, 4, 6
が指定できます。 その指定は C 言語の代入演算子 (+=, -=) の形式で行います。
 また、[W8] のようにオフセットなしの指定や、W9 と W12 の組み合わせに限定されますが、[W9+W12] の形のレジスタ・オフセットの指定もできます。
 データの格納先のレジスタは、乗算のオペランドとなる W4 ~ W7 のいずれかです。
 3 番目の「[W10]-=6, W7」は Y-バスからの読み出しに対する指定で、アドレス・レジスタ W10 および W11 を使う以外は X-バスからの読み出しと同様です。
 最後の「[W13]+=2」の部分は、「アキュムレータ・ライトバック」と呼ばれ、この命令で使ってない方のアキュムレータ (この場合は Acc A) をレジスタ W13 に直接格納するか、[W13]+=2 の 2 バイト・ポスト・インクリメント付きでメモリ書き込むかの、いずれかを指定することができます。
 2 チャネル・ステレオのデータを Acc A、Acc B に割り振る場合や、複素数の実部と虚部を Acc A、Acc B に割り振る場合など、交互にインターリーブされたプログラムで処理する場合に役立てることができます。
 たとえば、ステレオの L ch を Acc A に割り当て、L ch の処理が終わり Acc A に結果が保持されている状態で、Acc B の R ch の処理に移る段階で、「ついで」にAcc A をライトバックすることができます。