Main Content

最新のリリースでは、このページがまだ翻訳されていません。 このページの最新版は英語でご覧になれます。

サブシステムからの再呼び出し可能なコードの生成

コード ジェネレーターが同一の Atomic サブシステムに対して出力するコード量を削減するには、データを引数として渡す (たとえば、ブロックの入出力の場合は rtB_*、連続状態の場合は rtDW_*、およびパラメーターの場合は rtP_*) 再利用可能な関数としてサブシステムを設定できます。既定では、コード ジェネレーターは共有メモリに存在するグローバル データ構造体へのアクセスを共有して他のコードとやりとりするサブシステム コードを作成します。データを引数として渡すことで、コードは再呼び出し可能になります。コードの各インスタンスは独自の固有データを維持します。

再利用および再呼び出しが可能になるようサブシステムを設定するには、同一サブシステムのマスクおよびブロック パラメーターを同じ方法で設定します。コード ジェネレーターはチェックサムを実行してサブシステムが同一かどうか、およびコードが再利用可能かどうか判断します。コードが再利用可能な場合、コード ジェネレーターは再利用可能な再呼び出し可能関数コードの単一のインスタンスを生成します。

サブシステム ブロック パラメーターを設定するには、次の手順に従います。

  1. サブシステムがバーチャルの場合は、ブロック パラメーターAtomic サブシステムとして扱う, Treat as atomic unitAtomic サブシステムとして扱うTreat as atomic unitを選択して関数のパッケージ化パラメーターを有効にします。

  2. ブロック パラメーター関数のパッケージ化, Function packaging関数のパッケージ化Function packaging[再利用可能な関数] に設定します。コード ジェネレーターは、サブシステムごとに引数をもつ個別の関数を生成します。[再利用可能な関数] を選択すると、コード ジェネレーターがサブシステム コードに対して生成する関数とファイルの名前の制御に使用できる追加のパラメーターも有効になります。

  3. ブロック パラメーター関数名オプション, Function name options関数名オプションFunction name optionsの値を選択します。再利用可能な、再呼び出し可能コードを生成するには、同一のサブシステムに同じ設定を指定します。

    • コード ジェネレーターで関数名を決定させるには、[自動] を選択します。

    • サブシステム名 (ライブラリ ブロックの場合はライブラリ ブロックの名前) を使用するには、[サブシステム名を使用] を選択します。

    • ブロック パラメーター関数名, Function name関数名Function nameを表示し、一意の有効な C/C++ 関数名を入力するには、[ユーザー指定] を選択します。

    モデル参照階層内に同一サブシステムの複数のインスタンスが存在する場合は、[自動] を選択します。

    Embedded Coder® を使用している場合は、識別子の形式制御を使用できます。Identifier Format Control (Embedded Coder)を参照してください。

  4. ファイル名オプション, File name optionsファイル名オプションFile name optionsを設定します。再利用可能な、再呼び出し可能コードを生成するには、同一のサブシステムに同じ設定を指定します。

    • コード ジェネレーターでファイル名を決定させるには、[自動] を選択します。

    • サブシステム名 (ライブラリ ブロックの場合はライブラリ ブロックの名前) を使用するには、[サブシステム名を使用] を選択します。

    • 関数名を使用するには、ブロック パラメーター [関数名オプション] で指定したとおり、[関数名を使用] を選択します。

    • ブロック パラメーターファイル名 (拡張子なし), File name (no extension)ファイル名 (拡張子なし)File name (no extension)を表示し、拡張子 (.c.cpp など) を除くファイル名を入力するには、[ユーザー指定] を選択します。

    その他の考慮事項は次のとおりです。

    • モデル参照階層内に同一サブシステムの複数のインスタンスが存在する場合は、[自動] を選択します。

    • コード ジェネレーターでサブシステム用の別のファイルが生成されない場合、関数コードは、サブシステムの親システムから生成されたファイルに配置されます。親がモデルそれ自体である場合、コード ジェネレーターは関数コードを model.c または model.cpp に配置します。

    • 生成コードがソース管理の対象である場合は、[自動] 以外の値を指定します。このように指定すると、モデルを変更したり、リビルドするときに、生成されたファイル名は変更されません。

    • [サブシステム名を使用] を選択すると、モデルに Model ブロックが含まれている場合や、モデル参照のターゲットがモデルに対して生成されている場合、コード ジェネレーターはサブシステム ファイル名をマングルします。このような場合、コード ジェネレーターはファイル名 modelsubsystem.c を使用します。

サブシステム A にマスク パラメーター bK があり、サブシステム B にマスク パラメーター cK がある場合、コードの再利用は実行できません。コード ジェネレーターはサブシステム A と B 用に個別の関数を生成します。サブシステム A と B に個別にブロック パラメーターを設定する場合、コードの再利用は実行できません。

生成されたコードでの関数の再利用

この例では、Atomic サブシステムを再利用可能なコードの生成用に構成する方法を示します。サブシステム用に生成されたコードを Atomic サブシステムとして実行するように指定するには、[ブロック パラメーター] ダイアログ ボックスで [Atomic サブシステムとして扱う] パラメーターを選択します。このパラメーターにより、[コード生成] タブの [関数のパッケージ化] パラメーターが有効になります。[関数のパッケージ化] パラメーターには次の 4 つの設定があります。

  • Inline: サブシステム コードのインライン化

  • Nonreusable function: I/O がグローバル データとして渡される関数

  • Reusable function: I/O が関数の引数として渡される関数

  • Auto: コンテキストに基づいて Simulink Coder により最適化

Reusable function および Auto に設定すると、コード ジェネレーターでサブシステム コードの再利用が許可されます。Reusable function および Nonreusable function に設定すると、[関数名オプション][関数名][ファイル名オプション] のパラメーターが有効になります。

Embedded Coder のライセンスがある場合は、引数を受け入れるように再利用不可能なサブシステムを構成できます。

モデル例

rtwdemo_ssreuse モデルには、SS1 および SS2 という 2 つの同一のサブシステムが含まれています。これらのサブシステムでは、[関数のパッケージ化] パラメーターが Reusable function に設定され、[関数名] パラメーターが myfun になっています。これらのサブシステムはパラメーター化されたマスク サブシステムです。マスク サブシステムの内容を表示するには、サブシステム ブロックを右クリックし、[マスク][マスク内を表示] を選択します。

model = 'rtwdemo_ssreuse';
open_system(model);

コードの生成と検査

ビルドと検査プロセス用に一時フォルダーを作成します。Simulink Coder アプリまたは Embedded Coder アプリを開きます。次に、コードを生成して検査します。

currentDir=pwd;
[~,cgDir]=rtwdemodir();
rtwbuild(model)
### Starting build procedure for: rtwdemo_ssreuse
### Successful completion of build procedure for: rtwdemo_ssreuse
cfile=fullfile(cgDir, 'rtwdemo_ssreuse_grt_rtw', 'rtwdemo_ssreuse.c');
rtwdemodbtype(cfile, '/* Model step', '/* Model initialize', 1, 0);
/* Model step function */
void rtwdemo_ssreuse_step(void)
{
  /* Outputs for Atomic SubSystem: '<Root>/SS1' */

  /* Inport: '<Root>/In1' incorporates:
   *  Inport: '<Root>/In2'
   */
  myfun(rtwdemo_ssreuse_U.In1, rtwdemo_ssreuse_U.In2, &rtwdemo_ssreuse_B.SS1,
        rtwdemo_ssreuse_P.T1Data, rtwdemo_ssreuse_P.T1Break);

  /* End of Outputs for SubSystem: '<Root>/SS1' */

  /* Outport: '<Root>/Out1' */
  rtwdemo_ssreuse_Y.Out1 = rtwdemo_ssreuse_B.SS1.LookupTable;

  /* Outputs for Atomic SubSystem: '<Root>/SS2' */

  /* Inport: '<Root>/In1' incorporates:
   *  Inport: '<Root>/In2'
   */
  myfun(rtwdemo_ssreuse_U.In1, rtwdemo_ssreuse_U.In2, &rtwdemo_ssreuse_B.SS2,
        rtwdemo_ssreuse_P.T2Data, rtwdemo_ssreuse_P.T2Break);

  /* End of Outputs for SubSystem: '<Root>/SS2' */

  /* Outport: '<Root>/Out2' */
  rtwdemo_ssreuse_Y.Out2 = rtwdemo_ssreuse_B.SS2.LookupTable;
}

モデルのステップ関数に、再利用可能な関数 myfun の呼び出しが 2 つあります。マスク パラメーター T1BreakT1DataT2Break および T2Data は、関数の引数です。

[関数のパッケージ化] パラメーターを Inline に変更します。

set_param('rtwdemo_ssreuse/SS1','RTWSystemCode','Inline')
set_param('rtwdemo_ssreuse/SS2','RTWSystemCode','Inline')

コードを生成して検査します。

rtwbuild(model)
### Starting build procedure for: rtwdemo_ssreuse
### Successful completion of build procedure for: rtwdemo_ssreuse
cfile=fullfile(cgDir, 'rtwdemo_ssreuse_grt_rtw', 'rtwdemo_ssreuse.c');
rtwdemodbtype(cfile, '/* Model step', '/* Model initialize', 1, 0);
/* Model step function */
void rtwdemo_ssreuse_step(void)
{
  real_T Out1_tmp;

  /* Outputs for Atomic SubSystem: '<Root>/SS2' */
  /* Outputs for Atomic SubSystem: '<Root>/SS1' */
  /* Sum: '<S1>/Sum' incorporates:
   *  Inport: '<Root>/In1'
   *  Inport: '<Root>/In2'
   *  Sum: '<S2>/Sum'
   */
  Out1_tmp = rtwdemo_ssreuse_U.In1 + rtwdemo_ssreuse_U.In2;

  /* End of Outputs for SubSystem: '<Root>/SS2' */

  /* Outport: '<Root>/Out1' incorporates:
   *  Lookup_n-D: '<S1>/Lookup Table'
   *  Sum: '<S1>/Sum'
   */
  rtwdemo_ssreuse_Y.Out1 = look1_binlx(Out1_tmp, rtwdemo_ssreuse_P.T1Break,
    rtwdemo_ssreuse_P.T1Data, 10U);

  /* End of Outputs for SubSystem: '<Root>/SS1' */

  /* Outputs for Atomic SubSystem: '<Root>/SS2' */
  /* Outport: '<Root>/Out2' incorporates:
   *  Lookup_n-D: '<S2>/Lookup Table'
   */
  rtwdemo_ssreuse_Y.Out2 = look1_binlx(Out1_tmp, rtwdemo_ssreuse_P.T2Break,
    rtwdemo_ssreuse_P.T2Data, 10U);

  /* End of Outputs for SubSystem: '<Root>/SS2' */
}

モデルのステップ関数では、サブシステム コードはインライン化されます。

[関数のパッケージ化] パラメーターを Nonreusable function に変更します。SS2 の場合は、[関数名] パラメーターを myfun2 に変更します。

set_param('rtwdemo_ssreuse/SS1','RTWSystemCode','Nonreusable function')
set_param('rtwdemo_ssreuse/SS2','RTWSystemCode','Nonreusable function')
set_param('rtwdemo_ssreuse/SS2','RTWFcnName','myfun2')

コードを生成して検査します。

rtwbuild(model)
### Starting build procedure for: rtwdemo_ssreuse
### Successful completion of build procedure for: rtwdemo_ssreuse
cfile=fullfile(cgDir, 'rtwdemo_ssreuse_grt_rtw', 'rtwdemo_ssreuse.c');
rtwdemodbtype(cfile, '/* Model step', '/* Model initialize', 1, 0);
/* Model step function */
void rtwdemo_ssreuse_step(void)
{
  /* Outputs for Atomic SubSystem: '<Root>/SS1' */
  myfun();

  /* End of Outputs for SubSystem: '<Root>/SS1' */

  /* Outputs for Atomic SubSystem: '<Root>/SS2' */
  myfun2();

  /* End of Outputs for SubSystem: '<Root>/SS2' */
}

モデルのステップ関数に、関数 myfunmyfun2 の呼び出しが含まれています。これらの関数には void-void インターフェイスがあります。

[関数のパッケージ化] パラメーターを Auto に変更します。

set_param('rtwdemo_ssreuse/SS1','RTWSystemCode','Auto')
set_param('rtwdemo_ssreuse/SS2','RTWSystemCode','Auto')

auto 設定では、Simulink Coder は最適な形式を選択します。このモデルでは、最適な形式は再利用可能な関数です。

モデルを閉じてクリーンアップします。

bdclose(model)
rtwdemoclean;
cd(currentDir)

制限

  • コード ジェネレーターはチェックサムを使用して、サブシステムが同一であり再利用可能であるかどうかを判断します。次の場合、サブシステム コードは再利用されません。

    • ブロックとデータ オブジェクトで、シンボルを使用して次元を指定している。

    • 端子のサンプル時間、データ型、実数/複素数、フレーム ステータス、次元がサブシステムによって異なる。

    • サブシステムの出力がグローバル信号としてマークされている。

    • 名前やパラメーター設定の異なる同一ブロックがサブシステムに含まれている。

    • サブシステムの出力が Merge ブロックに接続されていて、Merge ブロックの出力がアドレス指定できないメモリ (BitField など) として C コードに実装されるカスタム ストレージ クラスを使用して設定されている。

    • サブシステムの入力が非スカラーで、アドレス指定できないメモリとして C コードに実装されるカスタム ストレージ クラスを使用して設定されている。

    • マスク サブシステムが非スカラーのパラメーターをもち、アドレス指定できないメモリとして C コードに実装されるカスタム ストレージ クラスを使用して設定されている。

    • モデル コンフィギュレーション パラメーターの既定のパラメーター動作[調整可能] に設定した場合に、Function-Call Subsystem はマスク パラメーターを使用する。マスクされた Function-Call Subsystem を再利用するには、それを新しい Atomic Subsystem 内にマスクなしで配置します。次に、Trigger ブロックをマスク サブシステムから Atomic Subsystem に移動します。

    • サブシステムのブロックは "部分的に調整可能な式" を使用する。部分的に調整可能な式によってはコードの再利用を無効にします。

      部分的に調整可能な式は、1 つ以上の調整可能な変数と調整不可能な式が含まれる式です。たとえば、値 15.23 をもつ調整可能な変数 K と、値 [5;7;9] をもつ調整可能な変数 P を作成すると仮定します。式 P' は調整不可能なので、式 K+P' は部分的に調整可能な式になります。調整可能な式の制限の詳細は、調整可能な式の制限を参照してください。

  • 再利用可能な S-Function ブロックを含むサブシステムでは、ブロックはS-Functions That Support Code Reuse (Embedded Coder)にリストされている要件を満たなければなりません。

  • [再利用可能な関数] が選択されていて、コード ジェネレーターがサブシステムのコードが再利用できないと判断すると、再利用できない別の関数が生成されます。その関数が再利用可能かどうかは、それが 1 つのサブシステムだけで使用されている場合でも、コード生成レポートで確認できる可能性があります。(関数として導入するのではなく) このような場合のコード ジェネレーターのインライン サブシステム コードが必要な場合は、関数のパッケージ化, Function packaging関数のパッケージ化Function packaging[自動] に設定します。

  • 再利用可能なサブシステムで共有のローカル データ ストアを使用し、モデル データ要素に対して既定のマッピングを構成している場合は、カテゴリ [Shared local data stores] の既定のストレージ クラス マッピングを [既定] に設定したままにします。

  • サブシステムにおける次のブロックの使用は、サブシステム コードの再利用を妨げる場合があります。

    • Scope ブロック (データ ログが有効化されている)

    • 一定基準を満たさない S-Function ブロック (S-Functions That Support Code Reuse (Embedded Coder)を参照)

    • To File ブロック (データ ログが有効化されている)

    • To Workspace ブロック (データ ログが有効化されている)

  • 再利用可能なライブラリ サブシステム (参照モデル間で共有されるサブシステム) の場合、コード ジェネレーターはチェックサムを使用してサブシステムが同一かどうかを判別します。コード ジェネレーターは再利用可能なライブラリ サブシステム コードを共有ユーティリティ フォルダーに置きますが、この再利用可能コードは最上位モデルや参照モデルの生成コードからは独立です。たとえば、再利用可能なライブラリ サブシステム コードは model.hmodel_types.h は含みません。

    コード ジェネレーターが共有ユーティリティ フォルダーに置き、かつモデル コード依存である再利用可能コードはコンパイルされません。コード ジェネレーターによって、再利用可能なライブラリ サブシステム コードがモデル コード依存であると判別されると、その再利用可能なサブシステム コードは共有ユーティリティ フォルダーに配置されません。再利用可能なライブラリ サブシステムが次の場合、コード ジェネレーターはモデル コード依存のコードを生成します:

    • Step ブロック、連続時間またはマルチレート ブロックなど、時間関連の機能を使用するブロックを含む。

    • 1 つ以上の Model ブロックを含む。

    • インライン化されていないサブシステムまたは再利用可能なライブラリ サブシステムを含む。

    • ストレージ クラス Auto が設定されていない信号を含む。コード ジェネレーターは非 Auto ストレージ クラスが設定されている変数を model.h に配置します。

    • ストレージ クラス Auto が設定されていないパラメーターを含む。

    • Enumeration、Simulink.Signal、Simulink.Parameter など、[データ スコープ][エクスポート] に設定されていないユーザー定義ストレージ クラスを含む。コード ジェネレーターは型定義を model_types.h に配置している場合があります。

    • プリプロセッサ条件を生成する Variant Subsystem である。コード ジェネレーターはバリアント オブジェクトを定義するプリプロセッサ命令を model_types.h に配置します。

上記の制限はライブラリベースのコード生成にも適用されます。詳細については、Library-Based Code Generation for Reusable Library Subsystems (Embedded Coder)を参照してください。

関連するトピック