Main Content

オーバーフローの検出

この例では、関数 fiaccel を使用したオーバーフローの検出方法について説明します。変換プロセスの数値テストの段階では、ツールはスケーリングされた double を使用して固定小数点コードのシミュレーションを実行します。その後、生成されたコード内で固定小数点データ型のオーバーフローを発生させる可能性のある値を生成する式をレポートします。

必要条件

この例を実行するには、次の製品をインストールしなければなりません。

新規フォルダーの作成と関連ファイルのコピー

  1. ローカルの書き込み可能なフォルダーに、関数 overflow.m を作成します。

    function y = overflow(b,x,reset)
        if nargin<3, reset = true; end
        persistent z p
        if isempty(z) || reset
            p = 0;
            z = zeros(size(b));
        end
        [y,z,p] = fir_filter(b,x,z,p);
    end
    function [y,z,p] = fir_filter(b,x,z,p)
        y = zeros(size(x));
        nx = length(x);
        nb = length(b);
        for n = 1:nx
            p=p+1; if p>nb, p=1; end
            z(p) = x(n);        
            acc = 0;
            k = p;
            for j=1:nb
                acc = acc + b(j)*z(k);
                k=k-1; if k<1, k=nb; end
            end        
            y(n) = acc;
        end
    end
    

  2. テスト ファイル overflow_test.m を作成して overflow アルゴリズムの演習を行います。

    function overflow_test
        % The filter coefficients were computed using 
        % the FIR1 function from Signal Processing Toolbox.
        %   b = fir1(11,0.25);
        b = [-0.004465461051254
             -0.004324228005260
             +0.012676739550326
             +0.074351188907780
             +0.172173206073645
             +0.249588554524763
             +0.249588554524763
             +0.172173206073645
             +0.074351188907780
             +0.012676739550326
             -0.004324228005260
             -0.004465461051254]';
        
        % Input signal
        nx = 256;
        t = linspace(0,10*pi,nx)';
    
        % Impulse
        x_impulse = zeros(nx,1); x_impulse(1) = 1;
    
        % Max Gain
        % The maximum gain of a filter will occur 
        % when the inputs line up with the
        % signs of the filter's impulse response.
        x_max_gain = sign(b)';
        x_max_gain = repmat(x_max_gain,ceil(nx/length(b)),1);
        x_max_gain = x_max_gain(1:nx);
    
    
        % Sums of sines
        f0=0.1; f1=2;
        x_sines = sin(2*pi*t*f0) + 0.1*sin(2*pi*t*f1);
    
        % Chirp
        f_chirp = 1/16;                  % Target frequency
        x_chirp = sin(pi*f_chirp*t.^2);  % Linear chirp
    
        x = [x_impulse,x_max_gain,x_sines,x_chirp];
        titles = {'Impulse','Max gain','Sum of sines','Chirp'};
        y = zeros(size(x));
    
        for i=1:size(x,2)
            reset = true;
            y(:,i) = overflow(b,x(:,i),reset);
        end
    
        test_plot(1,titles,t,x,y)
    
    end
    function test_plot(fig,titles,t,x,y1)
        figure(fig)
        clf
        sub_plot = 1;
        font_size = 10;
        for i=1:size(x,2)
            subplot(4,1,sub_plot)
            sub_plot = sub_plot+1;
            plot(t,x(:,i),'c',t,y1(:,i),'k')
            axis('tight')
            xlabel('t','FontSize',font_size);
            title(titles{i},'FontSize',font_size);
            ax = gca;
            ax.FontSize = 10;
        end
        figure(gcf)
    end
    

入力の読み込みや、入力値の設定、テストする関数の呼び出し、テスト結果の出力など、すべての前処理と後処理を実行するための独立したテスト スクリプトを作成することをお勧めします。

タイプ名前説明
関数のコードoverflow.mエントリポイントの MATLAB 関数
テスト ファイルoverflow_test.mMATLAB スクリプト。次をテストします。 overflow.m

構成オブジェクトの設定

  1. coder.FixptConfig オブジェクト fixptcfg を既定の設定で作成します。

    fixptcfg = coder.config('fixpt');
  2. テスト ベンチの名前を設定します。この例では、テスト ベンチ関数名は overflow_test です。

    fixptcfg.TestBenchName = 'overflow_test';
  3. 既定の語長を 16 に設定します。

    fixptcfg.DefaultWordLength = 16;

オーバーフロー検出の有効化

fixptcfg.TestNumerics = true;
fixptcfg.DetectFixptOverflows = true;

fimath オプションの設定

fimath Product mode および Sum modeKeepLSB に設定します。これらの設定は C 言語の整数演算の動作をモデル化します。

fixptcfg.fimath = 'fimath( ''RoundingMethod'', ''Floor'', ''OverflowAction'', ''Wrap'', ''ProductMode'', ''KeepLSB'', ''SumMode'', ''KeepLSB'')';

固定小数点への変換

浮動小数点の MATLAB 関数 overflow を固定小数点の MATLAB コードに変換します。テスト ファイルから型が推測されるので、fiaccel コマンドの入力型を指定する必要はありません。

fiaccel -float2fixed fixptcfg overflow

数値テスト段階でオーバーフローがレポートされます。

Overflow error in expression 'acc + b( j )*z( k )'. 
Percentage of Current Range = 104%.

結果のレビュー

この式内の加算または乗算がオーバーフローしているか判断します。乗算がオーバーフローしないように fimath ProductMode を FullPrecision に設定し、fiaccel コマンドを再度実行します。

fixptcfg.fimath = 'fimath( ''RoundingMethod'', ''Floor'', ''OverflowAction'', ''Wrap'', ''ProductMode'', ''FullPrecision'', ''SumMode'', ''KeepLSB'')';
fiaccel -float2fixed fixptcfg overflow

数値テスト段階で、継続してオーバーフローがレポートされ、式の加算でオーバーフローしていることが示されます。