ホーム フォーラム Texas Instruments マイコン C2000 IQ型のデジタル演算について

このトピックには4件の返信が含まれ、2人の参加者がいます。5 年、 3 ヶ月前 amatsu1 さんが最後の更新を行いました。

5件の投稿を表示中 - 1 - 5件目 (全5件中)
  • 投稿者
    投稿
  • #7427 返信

    amatsu1
    参加者

    IQ型のデジタル演算について

    デバイス型番:TMS320F28027

    いつも大変お世話になっております。

    早速ですが、以下の件についてご回答願います。
    (お忙しい中恐縮ですが、本日中にご回答いただけると幸いでございます)

    ①以下のようなソースコードを書いて動かしていましたが、日本語マニュアルP78の__IQmpyに関する記載から
    上位16bitしか取り出させておらず、HRPWMを活かせていない(整数部のみしか使っていない)のではないかと思い、
    日本語マニュアルP134のCMPAのレジスタを見て、上記の16を24へ変更しました。
    これでHRPWMを活かせると考えたのですが、出力が出なくなってしまいました。
    何故動かなくなったかご教示願います。

    #define GLOBAL_Q 16

    NxtCntVal_Ch1 = __IQmpy(K0,Ierror0_Ch1,16)+__IQmpy(K1,Ierror1_Ch1,16)+__IQmpy(K2,CtrlVal1_Ch1,16);
    EPwm3Regs.CMPA.all=__IQsat(NxtCntVal_Ch1, MAX_CNTVAL, MIN_CNTVAL);
    (全ての変数はIQ型です)

    ②以下のソースコードはA,Bでどちらが高速でしょうか。

    A. __IQmpy((600-EPwm3Regs.CMPA.half.CMPA),16384,16)
    B. (600-EPwm3Regs.CMPA.half.CMPA) >> 2

    以上、宜しくお願い致します。

    #7435 返信
    Yojiro
    Yojiro
    従業員

    amatsu1さん

    お問い合わせ①

    GLOBAL_Qの値は16で問題ないものと考えます。

    __IQmpy関数(アンダースコアが2つ)の場合には、IQmathライブラリではなく、組み込み関数(Intrinsics関数)が使用されます。この詳細動作につきましては、Compiler User’s Guideによると、以下の命令で構成されます。

    long dst = __IQmpy( long A, long B, int N )
    15 < N < 32 : ( 以下、XT = A が行われたあとの命令です)
    IMPYL   P, XT, B   ; A * B の下位32bitの計算(結果はPレジスタへ)
    QMPYL  ACC, XT, B  ; A * B の上位32bitの計算(結果はACCレジスタへ)
    LSL64   ACC:P, #(32 – N)   ; ACC:Pから(32-N)ビットを左シフト

    わかりやすく、1.5 * 1.5の計算を例に、どのような計算が行われているか考えてみます。

    #define GLOBAL_Q 16
    _iq A = _IQ(1.5);
    _iq B = _IQ(1.5);
    _iq result;

    result = __IQmpy( A, B, 16 );

    1.5を固定小数点で表すと、0x00018000になります。
    __IQmpy( A, B, GLOBAL_Q )を細かく見ていくと、

    IMPYL  P, 0x00018000, 0x00018000   → P = 0x40000000
    QMPYL  ACC, 0x00018000, 0x00018000  → ACC = 0x00000002
    LSL64 ACC:P, #(32-16)       → ACC😛 << 16 = (0x0000000240000000 << 16) = 0x0002400000000000
    ACC = 0x00024000

    となります。CMPA.all(CMPA(16bit):CMPAHR(8bit))と同じフォーマットで小数点以下(CMPAHR)も設定できる構成になっています。

    GLOBAL_Qは、少数ビットに何ビット使用するかを表すものですから、24を設定すると、32ビット中下位24ビットが小数部として使用されます。このとき、上記と同様に計算してみます。

    #define GLOBAL_Q 24
    _iq result;
    result = __IQmpy( _iq(1.5), _iq(1.5), 24)

    結果は、result = 0x02400000となります。

    この値をそのまま、CMPA.allに設定すると、整数部が期待値と異なってしまい、飽和処理でも正しい結果が出ないものと考えます。

     

    お問い合わせ②

    上記にも記載しましたが、__IQmpy関数では、3つの命令で構成されております。整数部しか使用されないのであれば、Bのシフト命令により1/4される方が、1命令少なくなりますので、その分高速になるものと考えます。

     

    以上、ご確認のほど、よろしくお願いいたします。

    • この返信は5 年、 3 ヶ月前に Yojiro Yojiro さんが編集しました。理由: Underline(Ctrl-u)が正しく反映されないため
    #7438 返信

    amatsu1
    参加者

    お世話になります。
    ご回答いただき、誠にありがとうございます。

    ①についてですが、私の記載が間違っており、大変恐縮なのですが、#define GLOBAL_Q 16はそのままで__IQmpyの第三引数を24に変えた方が良いのではないか?というご質問でした。
    と言いますのも、せっかくHRPWMにしたのに、第三引数が16では__IQmpyの結果が整数部だけになってしまい、
    EPwm3Regs.CMPA.allに上位16bitのみ数字が入り、下位16bitが0になってしまうと考えました。
    この理解は違いますでしょうか。

    以上、宜しくお願い致します。

    • この返信は5 年、 3 ヶ月前に  amatsu1 さんが編集しました。
    #7440 返信
    Yojiro
    Yojiro
    従業員

    __IQmpyの第三引数は、小数部のビット数を表します。先程の回答に計算結果を記載しておりますが、第三引数を16とした場合、1.5 (0x00018000) * 1.5 (0x00018000) = 0x00024000と 整数部0x0002, 小数部0x4000となり、2.25という小数部を含む結果が得られます。整数部のみとなることはございません。

    GLOBAL_Qを16として、__IQmpyのみ24とすると、ACC:Pが 0x00000002_40000000に対して8ビット左シフトとなりますので、resultは 0x0000_0240 と整数部が0、つまりCMPA=0, CMPAHR=0x02という値となります。

    ご確認のほど、よろしくお願いいたします。

    #7441 返信

    amatsu1
    参加者

    内容承知致しました。
    ご対応いただき、誠にありがとうございました。

5件の投稿を表示中 - 1 - 5件目 (全5件中)