Main Content

TLC での S-Function のインライン化

timesN チュートリアルの概要

目的: TLC で S-Function を扱う方法を理解する。

フォルダー: matlabroot/toolbox/rtw/rtwdemos/tlctutorial/timesN (開く)

このチュートリアルでは、既存の S-Function timesN の C コード バージョンを生成します。

チュートリアルのステップは次のとおりです。

  1. インラインでないコードの生成 — SimStruct と汎用 API を使用

  2. TLC を使用して S-Function をインライン化する理由 — インライン化の利点

  3. インライン化 S-Function の作成 — カスタム TLC コードを使用

S-Function の "ラップ" に関する情報と手法については、この後のチュートリアルで扱います。

インラインでないコードの生成

作業フォルダーのチュートリアル フォルダー tlctutorial/timesN に Simulink® S-Function timesN.c が用意されています。

この演習では、モデル sfun_xN からインラインでないコードを生成します。

  1. tlctutorial/timesN でファイル rename_timesN.tlc を見つけます。このファイルの名前を timesN.tlc に変更します。これにより、コードを生成できるようになります。

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

    mex timesN.c

    これにより、Simulink に付属しているバージョンが選択されなくなります。

  3. モデル sfun_xN を開きます。このモデルでは timesN S-Function を使用しています。ブロック線図は次のとおりです。

  4. [コンフィギュレーション パラメーター] ダイアログ ボックスを開き、[ソルバー] ペインを選択します。

  5. [終了時間]10.0 に設定します。

  6. [ソルバー オプション] を設定します。

    • [タイプ]Fixed-step

    • [ソルバー]Discrete (no continuous states)

    • [固定ステップ サイズ]0.01

  7. [最適化] ペインを選択し、[既定のパラメーター動作][調整可能] に設定されていることを確認します。

  8. [コード生成][コメント] ペインを選択し、[コメントを含める] が既定でオンになっていることを確認します。

  9. [コード生成] ペインを選択し、[コード生成のみ] をオンにします。

    [適用] をクリックします。

  10. Ctrl+B を押してモデルの C コードを生成します。

  11. 結果のファイル sfun_xN_grt_rtw/sfun_xN.c を開き、次に示す sfun_xN_output の部分を確認します。

/* Model output function */
static void sfun_xN_output(int_T tid)
{
  /* Sin: '<Root>/Sin' */
  sfun_xN_B.Sin = sin(sfun_xN_M->Timing.t[0] * sfun_xN_P.Sin_Freq +
                      sfun_xN_P.Sin_Phase) * sfun_xN_P.Sin_Amp +
    sfun_xN_P.Sin_Bias;

  /* S-Function Block: <Root>/S-Function */
  /* Multiply input by 3.0 */
  sfun_xN_B.timesN_output = sfun_xN_B.Sin * 3.0;

  /* Outport: '<Root>/Out' */
  sfun_xN_Y.Out = sfun_xN_B.timesN_output;
  UNUSED_PARAMETER(tid);
}

[コンフィギュレーション パラメーター] ダイアログ ボックスの [コード生成][コメント] ペインで [コメントを含める] が既定でオンになっているため、コードにコメントが表示されています。

TLC を使用して S-Function をインライン化する理由

コード ジェネレーターには、ユーザー記述のアルゴリズムやドライバーを呼び出すために使用できる汎用 API があります。API には、初期化、出力、導関数、終了などのさまざまなコールバック関数のほか、データ構造体も含まれます。これらのコードを記述すると、メモリ内でインスタンス化され、実行時に間接的な関数呼び出しを介して呼び出されます。これらを呼び出すたびに、スタック フレームやその他のオーバーヘッドが発生し、実行時間が長くなります。

リアルタイム環境では、ソリューションで呼び出されるステップが多い場合は特に、汎用 API の呼び出しが容認できないほど遅くなることがあります。コード ジェネレーターでは、S-Function を汎用 API から間接的に呼び出すのではなく、ユーザー記述のアルゴリズムを自動生成される関数内に組み込むことで、スタンドアロン アプリケーションを生成して S-Function を高速化できます。この形式の最適化を "インライン化" と呼びます。TLC で S-Function をインライン化すると、より高速で最適化されたコードが得られます。

TLC は C コード S-Function を記述する代わりにはならないことに注意してください。シミュレーションでは TLC ファイルは使用されないため、カスタム ブロックを Simulink で呼び出すには、引き続き S-Function を C で (または MATLAB ファイルとして) 記述しなければなりません。ただし、指定した S-Function をインライン化する TLC ファイルを準備すれば、ターゲット コードをはるかに効率的にすることができます。

インライン化 S-Function の作成

TLC では、S-Function と同じ名前の .tlc ファイルを検出した場合は常に "インライン化 S-Function" を作成します。.tlc ファイルが想定される形式になっていると仮定し、API のオーバーヘッドを発生させることなく、外部の S-Function と機能的に重複しているコードの作成を行います。以下の手順を実行して、このプロセスの仕組みを確認します。

  1. まだ準備していない場合は、tlctutorial/timesN でファイル rename_timesN.tlc を見つけます。コードの生成に使用できるように、このファイルの名前を timesN.tlc に変更します。ファイルの実行可能部分は次のとおりです。

    %implements "timesN" "C"
    
    %% Function: Outputs ===========================================================
    %%
    %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)> * %<gain>;
      %endroll
    
    %endfunction
  2. S-Function のインライン バージョンを作成します。

    1. [コンフィギュレーション パラメーター] ダイアログ ボックスの [最適化] ペインで、[既定のパラメーター動作][インライン] に設定し、[適用] をクリックします。

    2. ブロック線図のラベルを model: sfun_xN から model: sfun_xN_ilp に変更します。

    3. モデルを sfun_x2_ilp として保存します。

    4. Ctrl+B を押します。ソース ファイルが sfun_xN_ilp_grt_rtw という名前の新しいサブフォルダーに作成されます。

    5. 生成されたファイル sfun_xN_ilp.c のコードを調べます。

      /* Model output function */
      static void sfun_xN_ilp_output(int_T tid)
      {
        /* Sin: '<Root>/Sin' */
        sfun_xN_ilp_B.Sin = sin(sfun_xN_ilp_M->Timing.t[0]);
      
        /* S-Function Block: <Root>/S-Function */
        /* Multiply input by 3.0 */
        sfun_xN_ilp_B.timesN_output = sfun_xN_ilp_B.Sin * 3.0;
      
        /* Outport: '<Root>/Out' */
        sfun_xN_ilp_Y.Out = sfun_xN_ilp_B.timesN_output;
        UNUSED_PARAMETER(tid);
      }

      メモ

      コード ジェネレーターでは、コードを生成して実行可能ファイルをビルドするときに、特定のサブフォルダー (ビルド フォルダーと呼ばれる) を作成または使用してソース ファイル、オブジェクト ファイル、make ファイルを格納します。既定では、ビルド フォルダーに model_grt_rtw という名前が付けられます。

      [既定のパラメーター動作][インライン] に設定してもコードが変わっていないことに注目してください。これは、S-Function が TLC でインライン化されるためです。

  3. スタンドアロンのシミュレーションを作成して演習を続けます。

    1. [コンフィギュレーション パラメーター] ダイアログ ボックスの [コード生成] ペインで、[コード生成のみ] をオフにし、[適用] をクリックします。

    2. [コンフィギュレーション パラメーター] ダイアログ ボックスの [データのインポート/エクスポート] ペインで、[出力] をオンにします。

      これを指定すると、モデルの出力データのログが MATLAB ワークスペースに記録されます。

    3. Ctrl+B を押してコードを生成します。モデルがコンパイルされ、sfun_xN_ilp.exe (UNIX® システムの場合は sfun_xN_ilp) という名前の実行可能ファイルにリンクされます。

    4. スタンドアロンの実行可能ファイルを実行して、timesN.tlc ファイルで想定した出力が生成されることを確認します。実行するには、MATLAB コマンド ウィンドウで次のように入力します。

      !sfun_xN_ilp

      次のような応答が表示されます。

      ** starting the model **
      ** created sfun_xN_ilp.mat **
    5. sfun_xN_ilp.mat ファイルの内容を表示またはプロットして、スタンドアロンのモデルで生成された正弦の出力範囲が -3 ~ +3 であることを確認します。MATLAB コマンド ウィンドウで次のように入力します。

      load sfun_xN_ilp.mat
      plot (rt_yout)

ヒント

UNIX プラットフォームの場合、コマンド ウィンドウで構文 !./executable_name を使用して実行可能プログラムを実行します。必要に応じて、構文 ./executable_name を使用して OS シェルから実行可能プログラムを実行します。詳細については、外部コマンド、スクリプト、プログラムの実行を参照してください。

関連するトピック