Main Content

このページの内容は最新ではありません。最新版の英語を参照するには、ここをクリックします。

TLC コードのデバッグ

tlcdebug チュートリアルの概要

目的: TLC デバッガーを紹介します。ブレークポイントを設定する方法を学習し、TLC デバッガー コマンドを理解します。

次の例を開きます。

openExample('simulinkcoder/AdviceAboutTLCTutorialsExample')
cd(tlctutorial/tlcdebug)

ビルド プロセスが呼び出されるごとに TLC デバッガーが呼び出されるようにすることができます。このチュートリアルでは、これを使用して、simple_log というモデルの .tlc ファイル内のバグを検出します。このバグにより、モデルのスタンドアロン バージョンから出力される生成コードがシミュレーション出力と異なるものになっています。このチュートリアルでは、以下の手順を順を追って説明します。

  1. 入門 — モデルを実行して出力を検査

  2. モデルからのコードの生成と実行 — コンパイル済みの結果を元の出力と比較

  3. デバッガーの開始とそのコマンドの使用 — デバッガーで行える処理

  4. デバッグ timesN.tlc — 問題を特定

  5. バグの修正と確認 — バグを修正して修正を確認する簡単な方法

入門

  1. MATLAB® コマンド ウィンドウで、S-Function の MEX ファイルを作成します。

    mex timesN.c

    これにより、Simulink® ソフトウェアに付属しているバージョンが選択されなくなります。

    メモ

    まだ mex -setup を実行していない場合は、エラーが発生することがあります。

  2. モデル simple_log を開きます。モデルは次のとおりです。

  3. [コンフィギュレーション パラメーター] ダイアログ ボックスの [データのインポート/エクスポート] ペインで、[時間] および [出力] をオンにします。これにより、モデル変数が MATLAB ワークスペースに記録されます。

  4. モデルを実行します。[シミュレーション] タブで [実行] をクリックします。変数 toutyout が MATLAB ワークスペースに表示されます。

  5. MATLAB コマンド ウィンドウの [ワークスペース] ペインの yout をダブルクリックします。変数エディターで simple_log から出力された 6 行 1 列の配列が表示されます。以下のような表示になります。

    列 1 には、端子 out1 で収集された、6 つのタイム ステップの離散パルス出力 (3s と 0s) が含まれています。

次に、simple_log のスタンドアロン バージョンを生成します。それを実行し、結果を上に表示されている Simulink からの出力と比較します。

メモ

この演習のために、提供されている TLC ファイル timesN.tlc にはバグが含まれています。このバージョンは、それを使用しているモデルと同じフォルダーに配置されている必要があります。

モデルからのコードの生成と実行

  1. Ctrl+B キーを押します。

    コード ジェネレーターにより、C ソース コードが生成、コンパイル、リンクされます。MATLAB コマンド ウィンドウにビルドの進行状況が表示され、その最後に以下のメッセージが示されます。

    ### Created executable: simple_log.exe  
    ### Successful completion of build procedure 
        for model: simple_log
  2. 以下を入力して、作成したスタンドアロン モデルを実行します。

    !simple_log

    これにより、以下のメッセージが表示されます。

    ** starting the model **
    ** created simple_log.mat **
  3. ワークスペースに変数を配置して結果を検査します。[現在のフォルダー] ペインで simple_log.mat をダブルクリックしてから、[ワークスペース] ペインの rt_yout (変数 yout のスタンドアロン バージョン) をダブルクリックします。

    rt_youtyout と比較します。差異を確認します。rt_yout の値が変化した原因を考えます。

    TLC でビルド フォルダー (simple_log_grt_rtw) に配置された、生成された C コードを見れば、問題の特定に役立ちます。

  4. simple_log.c を編集し、その関数 MdlOutputs を確認します。以下に示されているようになっています。

    /* Model output function */
    static void simple_log_output(void)
    {
      /* DiscretePulseGenerator: '<Root>/Discrete Pulse Generator' */
      simple_log_B.DiscretePulseGenerator = (simple_log_DW.clockTickCounter < 1.0) &&
        (simple_log_DW.clockTickCounter >= 0) ? 1.0 : 0.0;
      if (simple_log_DW.clockTickCounter >= 2.0 - 1.0) {
        simple_log_DW.clockTickCounter = 0;
      } else {
        simple_log_DW.clockTickCounter++;
      }
    
      /* End of DiscretePulseGenerator: '<Root>/Discrete Pulse Generator' */
    
      /* S-Function (timesN): '<Root>/Gain1st' incorporates:
       *  Outport: '<Root>/Out1'
       */
      /* S-Function Block: <Root>/Gain1st */
      /* Multiply input by 3.0 */
      simple_log_Y.Out1 = simple_log_B.DiscretePulseGenerator * 1;
    }
    

最後の方にある以下の行に注意してください。

simple_log_B.first_output = simple_log_B.DiscretePulseGenerator * 1;
3.0 と 0.0 を交互に繰り返す変数を受け取るはずだったのに、なぜ正しくない積が出力に代入されたのかを考えます。デバッガーを使用して特定します。

デバッガーの開始とそのコマンドの使用

TLC デバッガーを使用してコード生成プロセスを監視します。既定では呼び出されないため、デバッガーを明示的に要求する必要があります。

  1. TLC デバッグ環境を設定し、アプリケーションのビルドを開始します。

    1. [コンフィギュレーション パラメーター][コード生成] ペインを選択し、オプション [.rtw ファイルを残す] および [コード生成時に TLC デバッガーを実行] を選択します。[OK] をクリックします。

    2. モデルをビルドします。

      MATLAB コマンド ウィンドウでビルド プロセスが記述されます。ビルドは timesN.tlc ファイルで停止し、コマンド プロンプトが表示されます。

      TLC-DEBUG>
  2. help」と入力して TLC デバッガー コマンドのリストを表示します。以下にデバッガーでできることをいくつか示します。

    • TLC スコープの各種エンティティを表示およびクエリする。

      TLC-DEBUG> whos CompiledModel
      TLC-DEBUG> print CompiledModel.NumSystems
      TLC-DEBUG> print TYPE(CompiledModel.NumSystems)
    • 現在のコンテキストでステートメントを調べる。

      TLC-DEBUG> list
      TLC-DEBUG> list 10,40
    • 次のコード行に移動する。

      TLC-DEBUG> next
    • 関数にステップインする。

      TLC-DEBUG> step
    • 入力信号 %<u> など、変数に定数値を代入する。

      TLC-DEBUG> assign u = 5.0
    • 現在の位置またはコードの他の部分にブレークポイントを設定する。

      TLC-DEBUG> break timesN.tlc:10
    • 次のブレークポイントまで実行する。

      TLC-DEBUG> continue
    • 設定したブレークポイントをクリアする。

      TLC-DEBUG> clear 1
      TLC-DEBUG> clear all
  3. TLC デバッガー コマンドを試した場合、残りのコードを実行してビルド プロセスを完了してから、simple_log を再度ビルドします。ビルドは timesN.tlc ファイルで停止し、コマンド プロンプトが表示されます。

    TLC-DEBUG>

timesN.tlc のデバッグ

次に、コードの問題の原因を調べて特定します。

  1. timesN.tlc の 20 行目にブレークポイントを設定します。

    TLC-DEBUG> break timesN.tlc:20
  2. ブレークポイントまで進むように TLC デバッガーに指示します。

    TLC-DEBUG> continue

    TLC は入力を処理し、進行状況をレポートして、timesN.tlc の 20 行目まで進んでその行を表示してから、一時停止します。

    ### Loading TLC function libraries
    ...
    ### Initial pass through model to cache user defined code
    .
    ### Caching model source code
    .
    Breakpoint 1
    00020:   %roll idx = RollRegions, lcv = RollThreshold, block, "Roller", rollVars
  3. whos コマンドを使用して現在のスコープの変数を確認します。

    TLC-DEBUG> whos
    Variables within: <BLOCK_LOCAL>
    gain                           Real
    rollVars                       Vector
    block                          Resolved
    system                         Resolved
  4. print コマンドを使用して変数を検査します (名前では大文字と小文字が区別されます)。

    TLC-DEBUG> print gain
    3.0
    
    TLC-DEBUG> print rollVars
    [U, Y]
  5. 1 ステップ実行します。

    TLC-DEBUG> step
    00021:     %<LibBlockOutputSignal(0, "", lcv, idx)> = \
  6. 組み込み関数であるため、next コマンドを使用して先に進めます。

    TLC-DEBUG> next
    .
    00022:     %<LibBlockInputSignal(0, "", lcv, idx)> * 1;

    これが、間違った定数出力 simple_log_B.first_output = simple_log_B.DiscretePulseGenerator * 1; の原因となった C ステートメントの起点です。

  7. TLC デバッガーを終了してビルドを破棄します。以下を入力します。

    TLC-DEBUG> quit

    エラー メッセージが表示され、TLC デバッガーの quit コマンドを使用してビルドを停止したことが示されます。エラー ウィンドウを閉じます。

バグの修正と確認

特定した問題の原因は、TLC 関数 FcnEliminateUnnecessaryParams() 内で変数ではなく定数を評価していることです。これは典型的なコーディング エラーであり、簡単に修正できます。以下に修正する必要のあるコードを示します。

%function Outputs(block, system) Output
   %assign gain =SFcnParamSettings.myGain
  /* %<Type> Block: %<Name> */
  %%
  /* Multiply input by %<gain> */
  %assign rollVars = ["U", "Y"]
  %roll idx = RollRegions, lcv = RollThreshold, block, "Roller", rollVars
    %<LibBlockOutputSignal(0, "", lcv, idx)> = \
    %<LibBlockInputSignal(0, "", lcv, idx)> * 1;
  %endroll

%endfunction

%% [EOF] timesN.tlc
  1. コーディング エラーを修正するには、timesN.tlc を編集します。以下の行では

    %<LibBlockInputSignal(0, "", lcv, idx)> * 1;
    評価された入力に 1 を乗算しています。この行を以下に変更します。
    %<LibBlockInputSignal(0, "", lcv, idx)> * %<gain>;

    timesN.tlc を保存します。

  2. スタンドアロン モデルを再度ビルドします。各 TLC-DEBUG> プロンプトで「continue」と入力してビルドを完了します。

  3. 以下を入力して、スタンドアロン モデルを実行します。

    !simple_log
    simple_log.mat の新しいバージョンが作成され、その出力が含まれます。

  4. 前と同様に、simple_log.mat を読み込んでワークスペース変数 rt_youtyout と比較します。これで、最初の列の値が同じになっています。

関連するトピック