概要
今回はdsPIC33AKシリーズの強化されたDSPの性能について検証します。
| 更新日 | 更新内容 |
| 24/8/21 | 初版 |
| 25/3/24 | リンク先追加 |
関連記事
内部リンク
外部リンク
| タイトル | リンク先 |
| XC-DSCライブラリリファレンスマニュアル (PDF) | MPLAB XC-DSC Libraries Reference Manual |
| XC-DSCライブラリリファレンスマニュアル (オンライン) | https://onlinedocs.microchip.com/oxy/GUID-70ACD6B0-A33F-4653-B192-8465EAD1FD98-en-US-11/index.html |
| XC-DSCコンパイラユーザーズガイド (オンライン) | MPLAB XC-DSC C Compiler User’s Guide |
開発環境
開発環境を以下に示します。
今回はどちらのCPUボードでも動作いたします。
| 項目 | 値 | リンク |
| ベースボード | dsPIC33A CURIOSITY PLATFORM DEVELOPMENT BOARD | dsPIC33A Curiosity Platform Development Board User’s Guide (microchip.com) |
| CPUボード(EV68M17A) | EV68M17A – dsPIC33AK128MC106 Motor Control DIM | dsPIC33AK128MC106 Motor Control Dual In-Line Module (DIM) Information Sheet (microchip.com) |
| CPUボード(EV02G02A) | dsPIC33AK128MC106 General Purpose Dual In-Line Module (DIM) | dsPIC33AK128MC106 General Purpose Dual In-Line Module (DIM) | Microchip Technology |
| 統合開発環境 | MPLAB X IDE v6.20 | MPLAB® X IDE | Microchip Technology |
| コンパイラ | MPLAB XC DSC v3.10 | MPLAB® XC DSC Compiler | Microchip Technology |

概要
dspPIC33AKシリーズのDSP(*1)の乗算器は33×33ビットをサポートするようになりました。アキュムレータも従来の2×40ビットから2×72ビットに拡張されているため、従来は演算が飽和していた処理でも、より演算が飽和しにくくなりました。またMAC命令も改良され任意のワーキングレジスタを利用可能、またプリフェッチも必要としないため、構文が大幅に改善されています。
DSP(Digital Signal Processor、デジタル信号プロセッサ)とは、デジタル信号処理に特化したマイクロプロセッサのことを指します。DSPは、音声、画像、ビデオ、センサーデータなどのデジタル信号をリアルタイムで処理するために設計されています。これにより、DSPは通信、マルチメディア、医療機器、産業オートメーションなど、幅広い応用分野で使用されています。
DSPブロック図
下記にDSPブロック図

DSP命令
| 命令 | 機能 | 代数的等価 |
| MAC | 乗算してアキュムレータに加算、 または二乗してアキュムレータに加算 | a = a + b * c a = a + b2 |
| MSC | 乗算とアキュムレータからの減算 | a = a – b * c |
| MPY | 乗算 | a = b * c |
| MPYN | 乗算と符号反転 | a = -b * c |
| SQR | 二乗 | a = b ^ 2 |
| SQRAC | 二乗してアキュムレータに加算 | a = a + (b ^ 2) |
| ED | 差の二乗 | a = (b – c)2 |
| EDAC | 差の二乗をアキュムレータに加算 | a = a + (b – c)2 |
DSPライブラリ
下記にDSPライブラリを示します。
<dsp.h>のインクルードと’libdsp-elf.a.’のライブラリ読込が必要です。
■ベクタ関数
| 関数名 | 機能 |
| VectorAdd | ソース1ベクトル内の各要素の値を、ソース2ベクトル内の対応する要素と加算し、その結果をデスティネーションベクトルに配置します。 |
| VectorConvolve | 2 つの入力ベクトル間の畳み込みを計算し、その結果を出力ベクトルに格納 |
| VectorCopy | ソースベクトル内の各要素の値を、デスティネーションベクトル内の各要素にコピー |
| VectorCorrelate | 2 つの入力ベクトル間の相関を計算し、その結果を出力ベクトルに格納 |
| VectorDotProduct | ソース 1 およびソース 2 ベクトルの対応する要素間の積の合計を計算 |
| VectorMax | ベクトル内の最大値を算出 |
| VectorMin | ベクトル内の最小値を算出 |
| VectorMultiply | ソース1ベクトルの各要素の値とソース2ベクトルの対応する値を乗算し、 結果をデスティネーションベクトルの対応する要素に配置 |
| VectorNegate | ソースベクトル内の各要素の値を、デスティネーションベクトル内の各要素に符号を反転してコピー |
| VectorPower | ソース・ベクトルのパワーを、その要素の2乗の和として計算 |
| VectorScale | ソースベクトルのすべての要素の値をスケール値でスケーリング(乗算)し、その結果をデスティネーションベクトルに配置 |
| VectorSubtract | ソース2ベクトルの各要素の値を、ソース1ベクトルの対応する値から引き、結果をデスティネーションベクトルに配置 |
| VectorZeroPad | VectorZeroPadは、コピー元ベクトルを(すでに存在する)コピー先ベクトルの先頭にコピーし、コピー先ベクトルの残りのnumZeros個の要素をゼロで埋める |
■ウィンドウ関数
| 関数名 | 機能 |
| BartlettInit | バーレット窓を初期化 |
| BlackmanInit | ブラックマン窓を初期化 |
| HammingInit | ハミング窓を初期化 |
| HanningInit | ハニング窓を初期化 |
| KaiserInit | カイザー窓を初期化 |
| VectorWindow | 指定された入力ベクトルにウィンドウを適用し、その結果生じるウィンドウ付きベクトルを出力ベクトルに格納 |
■マトリックス関数
| 関数名 | 機能 |
| MatrixAdd | 入力行列 1 の各要素の値を、入力行列 2 の各要素の値と加算し、その結果を出力行列に格納 |
| MatrixMultiply | 入力行列 1 と入力行列 2 の間の行列乗算を実行し,結果を出力行列に格納 |
| MatrixScale | 入力行列のすべての要素の値をスケール値でスケーリング(乗算)し,その結果を出力行列に配置 |
| MatrixSubtract | 入力 2 行列の各要素の値を,入力 1 行列の各要素の値から減算し,その結果を出力行列に格納 |
| MatrixTranspose | 入力行列の行を列で転置し,その結果を出力行列に配置 |
| MatrixInvert | 入力行列の逆行列を計算し,その結果を出力行列に格納 |
■フィルター関数
| 関数名 | 機能 |
| FIR | FIRフィルターの実行 |
| FIRDecimate | FIRフィルターとデシメーションの実行 |
| FIRDelayInit | FIRStructフィルター構造体の遅延値をゼロに初期化 |
| FIRInterpolate | ソースサンプルをアップサンプルしFIRフィルターを実行 |
| FIRInterpDelayInit | IR補間フィルター用に最適化されたFIRStructフィルター構造体の遅延値を ゼロに初期化 |
| FIRLattice | 格子構造の実装を使用して、ソースサンプルのシーケンスにFIRフィルタを適用 |
| FIRLMS | 適応FIRフィルタの実行 フィルタ係数は、参照サンプルの値に応じて適用される最小平均二乗アルゴリズムを使用して、サンプルごとに更新 |
| FIRLMSNorm | 適応FIRフィルタの実行 フィルタ係数は、参照サンプルの値に応じて適用される正規化最小平均二乗アルゴリズムを用いて、サンプルごとに更新 |
| FIRStructInit | FIRStruct FIRフィルター構造体のパラメーターの値を初期化 |
| IIRCanonic | ソースサンプルのシーケンスに、カノニック(直接形II)2次セクションのカスケードを使用して、IIR フィルタを適用 |
| IIRCanonicInit | IIRCanonicStructフィルター構造体の遅延値をゼロに初期化 |
| IIRLattice | 格子構造の実装を使用して、ソースサンプルのシーケンスに IIR フィルタを 適用 |
| IIRLatticeInit | IIRLatticeStructフィルター構造体の遅延値をゼロに初期化 |
| IIRTransposed | ソースサンプルのシーケンスに、転置された(直接形式II)2次セクションの カスケードを使用して、IIRフィルタを適用 |
| IIRTransposedInit | IIRTransposedStructフィルター構造体の遅延値をゼロに初期化 |
■変換関数
| 関数名 | 機能 |
| BitReverseComplex | 複素数ベクトルの要素をビット逆順に並べ替えを実行 |
| BitReverseReal32bIP | 32ビット実数ベクトルの要素をビット逆順に並べ替えを実行 |
| CosFactorInit | II型離散コサイン変換で必要とされるコサイン係数のセットの前半を生成し、その結果を複素数の出力ベクトルに配置 |
| DCT | ソースベクトルの離散コサイン変換を計算し、その結果をデスティネーションベクトルに格納 |
| DCTIP | ソースベクトルの離散コサイン変換を計算 |
| FFTComplex | ソース複素数ベクトルの高速フーリエ変換を計算し、結果をデスティネーション複素数ベクトルに格納 |
| FFTReal32b | 32ビット実数ソースベクトルの32ビット高速フーリエ変換を計算し、結果を32ビット実数デスティネーションベクトルに格納 |
| FFTComplexIP | ソース複素数ベクトルの高速フーリエ変換を計算 |
| FFTComplex32bIP | ソース複素数ベクトルの32ビット高速フーリエ変換を計算 |
| FFTReal32bIP | 32ビット実数ソースベクトルの32ビット高速フーリエ変換を計算 |
| IFFTComplex | ソース複素数ベクトルの逆高速フーリエ変換を計算し、結果をデスティネーション複素数ベクトルに格納 |
| IFFTReal32b | 32ビット実数ソースベクトルの32ビット逆高速フーリエ変換を計算し、結果を32ビット実数デスティネーションベクトルに格納 |
| IFFTComplexIP | 複素数ベクトルの逆高速フーリエ変換を計算 |
| IFFTComplex32bIP | 複素数ベクトルの32ビット逆高速フーリエ変換を計算 |
| IFFTReal32bIP | 2ビット実数ソース・ベクトルの32ビット逆高速フーリエ変換をその場で計算 |
| SquareMagnitudeCplx | 複素ソース・ベクトルの各要素の大きさの2乗を計算 |
| MagnitudeCplx32bIP | 32 ビット複素ソース・ベクトルの各要素の 32 ビット二乗マグニチュードを計算 |
| TwidFactorInit | 離散フーリエ変換または離散コサイン変換で必要とされるトウィドル因子のセットの前半を生成 |
■制御関数
| 関数名 | 機能 |
| PIDInit | controlHistory が指す 3 要素配列の遅延線要素をクリア |
| PIDCoeffCalc | PID係数の初期化 |
| PID | PIDの実行 |
■変換関数
| 関数名 | 機能 |
| Fract2Float | fractional をfloatに変換 |
| Float2Fract | floatをfractional に変換 |
■スタック関数
| 関数名 | 機能 |
| SetStackGuard | スタックガード値を変更 |
DSPビルトイン関数
下記にビルトイン関数を示します。DSP命令を出力する関数は青字で示しています。
| No. | ビルトイン関数 | 機能 | 機械語 |
| 28.2.3 | __builtin_add_16 | シフトされた値をアキュムレータに加算 | add |
| 28.2.4 | __builtin_add_32 | シフトされた値をアキュムレータに加算 | add |
| 28.2.7 | __builtin_and_RCR | 浮動小数点コントロール・レジスタ( FCR )のビットクリア | and |
| 28.2.11 | __builtin_btg_32 | ビット反転 | btg |
| 28.2.12 | __builtin_clr | アキュムレータクリア | clr a |
| 28.2.18 | __builtin_div_3216 | 32bitと16bitの固定小数点除算 | divs.l |
| 28.2.20 | __builtin_divf_16 | 16bit同士の固定小数点除算 | divf.w |
| 28.2.21 | __builtin_divf_32 | 32bit同士の固定小数点除算 | divfl |
| 28.2.22 | __builtin_divf_3216 | 混合固定小数点除算 | divf.l |
| 28.2.23 | __builtin_divmod_3216 | 混合固定小数点除算と余りを出力 | divs.l |
| 28.2.24 | __builtin_divmodf | 32bit固定小数点除算と余りをキャプチャ | divfl |
| 28.2.25 | __builtin_divmodf_16 | 16bit固定小数点除算と余りをキャプチャ | divf.w |
| 28.2.34 | __builtin_ed_16 | (x-y)2の部分ユークリッド距離を計算し 結果をアキュムレータに格納 (16bit) | ed.w |
| 28.2.35 | __builtin_ed_32 | (x-y)2の部分ユークリッド距離を計算し 結果をアキュムレータに格納 (32bit) | ed.l |
| 28.2.37 | __builtin_edac_16 | (x-y)2の部分ユークリッド距離を計算し アキュムレータに加算 (16bit) | edac.w |
| 28.2.38 | __builtin_edac_32 | (x-y)2の部分ユークリッド距離を計算し アキュムレータに加算 (32bit) | edac.l |
| 28.2.42 | __builtin_fbcl | 値の左(Msb)から最初のビット変化を見つける | fbcl |
| 28.2.43 | __builtin_fbcl_16 | 符号ビットを飛ばして、左から最初のビット変化を見つける(16bit) | fbcl |
| 28.2.44 | __builtin_fbcl_32 | 符号ビットを飛ばして、左から最初のビット変化を見つける(32bit) | fbcl.l |
| 28.2.45 | __builtin_ff1l | 値の左(Msb)から最初の1を見つける(32bit) | ff1l |
| 28.2.45 | __builtin_ff1r | 値の右(Lsb)から最初の1を見つける(32bit) | ff1r |
| 28.2.46 | __builtin_ff1l_16 | 値の左(Msb)から最初の1を見つける(16bit) | ff1l |
| 28.2.47 | __builtin_ff1l_32 | 値の左(Msb)から最初の1を見つける(32bit) | ff1l.l |
| 28.2.48 | __builtin_ff1r_16 | 値の右(Lsb)から最初の1を見つける(16bit) | ff1r |
| 28.2.49 | __builtin_ff1r_32 | 値の右(Lsb)から最初の1を見つける(32bit) | ff1r.l |
| 28.2.51 | __builtin_flim_32 | 強制(符号付き)データ範囲制限(32bit) | flim.l |
| 28.2.53 | __builtin_flim_excess_32 | 強制(符号付き)データ・レンジ・リミットとリミット超過結果 | flim.l |
| 28.2.55 | __builtin_flimv_excess_32 | 強制(符号付き)データ・レンジ・リミットとリミット超過結果 | flim.lv |
| 28.2.56 | __builtin_fmax | 強制(符号付き)最大リミット | fmax |
| 28.2.57 | __builtin_fmax_excess | 強制(符号付き)最大リミットとリミット 超過結果 | fmax.v |
| 28.2.58 | __builtin_fmaxv_excess | 強制(符号付き)最大リミットとリミット 超過結果 | fmax.v |
| 28.2.59 | __builtin_fmin | 強制(符号付き)最小リミット | fmin |
| 28.2.60 | __builtin_fmin_excess | 強制(符号付き)最小リミットとリミット 超過結果 | fmin.v |
| 28.2.61 | __builtin_fminv_excess | 強制(符号付き)最小リミットとリミット 超過結果 | fmin.v |
| 28.2.62 | __builtin_get_isr_state | 現在のCPU割り込み状態の取得 | – |
| 28.2.63 | __builtin_ior_FCR | 浮動小数点制御(FCR )レジスタのビット設定 | ior |
| 28.2.65 | __builtin_lac_16 | シフトおよびアキュムレータロード(16bit) | lac |
| 28.2.66 | __builtin_lac_32 | シフトおよびアキュムレータロード(32bit) | lac |
| 28.2.70 | __builtin_mac_16 | アキュムレート付き 16 ビット乗算 | mac |
| 28.2.71 | __builtin_mac_32 | アキュムレート付き 32 ビット乗算 | mac.l |
| 28.2.73 | __builtin_max_16 | 最大値選択(16bit) | max.w |
| 28.2.73 | __builtin_max_32 | 最大値選択(32bit) | max.l |
| 28.2.77 | __builtin_min_16 | 最小値選択(16bit) | min.w |
| 28.2.77 | __builtin_min_32 | 最小値選択(32bit) | min.l |
| 28.2.80 | __builtin_mod_3216 | 混合モード整数モジュラス演算 | divs.l |
| 28.2.85 | __builtin_mpy_16 | アキュムレータへの 16 ビット乗算 | mpy |
| 28.2.86 | __builtin_mpy_32 | アキュムレータへの 32 ビット乗算 | mpy.l |
| 28.2.88 | __builtin_mpyn_16 | 16 ビットの乗算とアキュムレータへのネゲート | mpyn |
| 28.2.89 | __builtin_mpyn_32 | 32 ビットの乗算とアキュムレータへのネゲート | mpyn.l |
| 28.2.91 | __builtin_msc_16 | アキュムレータからの 16 ビット乗算および減算 | msc |
| 28.2.92 | __builtin_msc_32 | アキュムレータからの 32 ビット乗算および減算 | msc.l |
| 28.2.94 | __builtin_mulss_16 | 16ビット符号付き乗算(出力32ビット) | mulss.w |
| 28.2.95 | __builtin_mulss_32 | 32ビット符号付き乗算(出力64ビット) | mulss.d |
| 28.2.97 | __builtin_mulsu_16 | 混合符号の16ビット乗算(出力32ビット) | mulsu.w |
| 28.2.98 | __builtin_mulsu_32 | 混合符号の64ビット乗算(出力32ビット) | mulsu.d |
| 28.2.100 | __builtin_mulus_16 | 混合符号の16ビット乗算(出力32ビット) | mulus.w |
| 28.2.101 | __builtin_mulus_32 | 混合符号の64ビット乗算(出力32ビット) | mulus.d |
| 28.2.103 | __builtin_muluu_16 | 16ビット符号なし乗算(出力32ビット) | muluu.w |
| 28.2.104 | __builtin_muluu_32 | 32ビット符号なし乗算(出力64ビット) | muluu.d |
| 28.2.110 | __builtin_pwrsav | パワーセーブ | pwrsav |
| 28.2.111 | __builtin_repeat_nop | 繰り返しNop生成 | repeat * nop |
| 28.2.114 | __builtin_sac_16 | シフト(切り捨て)と16ビットへの丸め | sac |
| 28.2.115 | __builtin_sac_32 | シフト(切り捨て)と32ビットへの丸め | ? |
| 28.2.118 | __builtin_sacr_16 | シフト(ラウンド)と16ビットへの丸め | sac.r |
| 28.2.119 | __builtin_sacr_32 | シフト(ラウンド)と32ビットへの丸め | sacr.l |
| 28.2.122 | __builtin_set_isr_state | 現在のCPU割り込み状態のセット | – |
| 28.2.123 | __builtin_set_FCR | 浮動小数点コントロール・レジスタ(FCR)に値をセット | mov.l |
| 28.2.124 | __builtin_sftac | アキュムレータのシフト | sftac |
| 28.2.128 | __builtin_swap_32 | バイトスワップ | swap.l |
| 28.2.141 | __builtin_udiv | 混合モードの符号なし除算(16bit) | divu.l |
| 28.2.142 | __builtin_udivmod_3216 | 混合モードの符号なし除算 | divu.l |
| 28.2.143 | __builtin_umod_3216 | 混合モードの符号なしモジュラス演算 | divu.l |
| 28.2.144 | __builtin_write_ACCH | アキュムレータ書込み | lac.l |
| 28.2.145 | __builtin_write_ACCL | アキュムレータ書込み | llac.l |
| 28.2.146 | __builtin_write_ACCU | アキュムレータ書込み | luac.l |
| 28.2.149 | __builtin_write_DISICTL | 閾値以下の割り込み禁止 | disictl |
扱う数値について
従来のdsPICは下記のとおり、-1 ~0.999969482 の範囲をQ15フォーマットで表現していました。
| 項目 | 値 |
| フォーマット | Q15(1.15) |
| 範囲 | -1.0 ~ 0.999969482 |
| ビットポジション | ![]() |
| 整数⇔fractional 対応 表 | ![]() |
dspPIC33AKシリーズのDSPの乗算器は33×33ビットをサポートするようになったため、Q31フォーマットで表現します。
| 項目 | 値 |
| flactional | Q31(1.31) |
| 範囲 | -1.0 ~ 0.9999999995343387 |
| ビットポジション | ![]() |
| 整数⇔fractional 対応 表 | ![]() |
私が最初にDSPを上手く動かせなかった原因の一つが、この意識の違いでした。例えば、-0.3 * 0.5のような計算をビルトイン関数を使って整数で表現する場合、下表のとおり非常に大きな値が必要になることがあります。
| dsPIC33 F/E/C シリーズ | dsPIC33Aシリーズ |
| __builtin_mulsu( -9830, 16384) >> 15 | __builtin_mulsu(-644245094 ,1073741824 ) >> 31 |
記事についての注意点
本記事は慎重に内容を検討し正確さに努めておりますが、もし内容に誤りがあったとしても、この記事を参考にして生じた損害等については一切の責任を負いません。





コメント