サブシステムからの再呼び出し可能なコードの生成
コード ジェネレーターが同一の Atomic サブシステムに対して出力するコード量を削減するには、データを引数として渡す (たとえば、ブロックの入出力の場合は rtB_*
、連続状態の場合は rtDW_*
、およびパラメーターの場合は rtP_*
) 再利用可能な関数としてサブシステムを設定できます。既定では、コード ジェネレーターは共有メモリに存在するグローバル データ構造体へのアクセスを共有して他のコードとやりとりするサブシステム コードを作成します。データを引数として渡すことで、コードは再呼び出し可能になります。コードの各インスタンスは独自の固有データを維持します。
再利用および再呼び出しが可能になるようサブシステムを設定するには、同一サブシステムのマスクおよびブロック パラメーターを同じ方法で設定します。コード ジェネレーターはチェックサムを実行してサブシステムが同一かどうか、およびコードが再利用可能かどうか判断します。コードが再利用可能な場合、コード ジェネレーターは再利用可能な再呼び出し可能関数コードの単一のインスタンスを生成します。
サブシステム ブロック パラメーターを設定するには、次の手順に従います。
サブシステムがバーチャルの場合は、ブロック パラメーターAtomic サブシステムとして扱うを選択して関数のパッケージ化パラメーターを有効にします。
ブロック パラメーター 関数のパッケージ化 を
[再利用可能な関数]
に設定します。コード ジェネレーターは、サブシステムごとに引数をもつ個別の関数を生成します。[再利用可能な関数]
を選択すると、コード ジェネレーターがサブシステム コードに対して生成する関数とファイルの名前の制御に使用できる追加のパラメーターも有効になります。ブロック パラメーター 関数名オプション の値を選択します。再利用可能な、再呼び出し可能コードを生成するには、同一のサブシステムに同じ設定を指定します。
コード ジェネレーターで関数名を決定させるには、
[自動]
を選択します。サブシステム名 (ライブラリ ブロックの場合はライブラリ ブロックの名前) を使用するには、
[サブシステム名を使用]
を選択します。ブロック パラメーター 関数名 を表示し、一意の有効な C/C++ 関数名を入力するには、
[ユーザー指定]
を選択します。
モデル参照階層内に同一サブシステムの複数のインスタンスが存在する場合は、
[自動]
を選択します。Embedded Coder® を使用している場合は、識別子の形式制御を使用できます。Identifier Format Control (Embedded Coder)を参照してください。
関数名オプションを設定します。再利用可能な、再呼び出し可能コードを生成するには、同一のサブシステムに同じ設定を指定します。
コード ジェネレーターでファイル名を決定させるには、
[自動]
を選択します。サブシステム名 (ライブラリ ブロックの場合はライブラリ ブロックの名前) を使用するには、
[サブシステム名を使用]
を選択します。関数名を使用するには、ブロック パラメーター [関数名オプション] で指定したとおり、
[関数名を使用]
を選択します。ブロック パラメーターファイル名 (拡張子なし)を表示し、拡張子 (
.c
や.cpp
など) を除くファイル名を入力するには、[ユーザー指定]
を選択します。
その他の考慮事項は次のとおりです。
モデル参照階層内に同一サブシステムの複数のインスタンスが存在する場合は、
[自動]
を選択します。コード ジェネレーターでサブシステム用の別のファイルが生成されない場合、関数コードは、サブシステムの親システムから生成されたファイルに配置されます。親がモデルそれ自体である場合、コード ジェネレーターは関数コードを
またはmodel
.c
に配置します。model
.cpp生成コードがソース管理の対象である場合は、
[自動]
以外の値を指定します。このように指定すると、モデルを変更したり、リビルドするときに、生成されたファイル名は変更されません。[サブシステム名を使用]
を選択すると、モデルに Model ブロックが含まれている場合や、モデル参照のターゲットがモデルに対して生成されている場合、コード ジェネレーターはサブシステム ファイル名をマングルします。このような場合、コード ジェネレーターはファイル名model
subsystem
.c
を使用します。
サブシステム A にマスク パラメーター b
と K
があり、サブシステム B にマスク パラメーター c
と K
がある場合、コードの再利用は実行できません。コード ジェネレーターはサブシステム 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® のライセンスがある場合は、引数を受け入れるように再利用不可能なサブシステムを構成できます。
モデル例
GeneratedCodeFunctionReuse
モデルには、SS1
および SS2
という 2 つの同一のサブシステムが含まれています。これらのサブシステムでは、[関数のパッケージ化] パラメーターが Reusable
function
に設定され、[関数名] パラメーターが myfun
になっています。これらのサブシステムはパラメーター化されたマスク サブシステムです。マスク サブシステムの内容を表示するには、サブシステム ブロックを右クリックし、[マスク]、[マスク内を表示] を選択します。
model = 'GeneratedCodeFunctionReuse';
open_system(model);
コードの生成と検査
Simulink Coder アプリまたは Embedded Coder アプリを開きます。次に、コードを生成して検査します。
slbuild(model)
### Starting build procedure for: GeneratedCodeFunctionReuse ### Successful completion of build procedure for: GeneratedCodeFunctionReuse Build Summary Top model targets built: Model Action Rebuild Reason ============================================================================================================ GeneratedCodeFunctionReuse Code generated and compiled. Code generation information file does not exist. 1 of 1 models built (0 models already up to date) Build duration: 0h 0m 11.963s
cfile=fullfile(pwd, 'GeneratedCodeFunctionReuse_grt_rtw', 'GeneratedCodeFunctionReuse.c'); coder.example.extractLines(cfile, '/* Model step', '/* Model initialize', 1, 0);
/* Model step function */ void GeneratedCodeFunctionReuse_step(void) { /* Outputs for Atomic SubSystem: '<Root>/SS1' */ /* Inport: '<Root>/In1' incorporates: * Inport: '<Root>/In2' */ myfun(GeneratedCodeFunctionReuse_U.In1, GeneratedCodeFunctionReuse_U.In2, GeneratedCodeFunctionReuse_P.T1Data, GeneratedCodeFunctionReuse_P.T1Break, &GeneratedCodeFunctionReuse_B.SS1); /* End of Outputs for SubSystem: '<Root>/SS1' */ /* Outport: '<Root>/Out1' */ GeneratedCodeFunctionReuse_Y.Out1 = GeneratedCodeFunctionReuse_B.SS1.LookupTable; /* Outputs for Atomic SubSystem: '<Root>/SS2' */ /* Inport: '<Root>/In1' incorporates: * Inport: '<Root>/In2' */ myfun(GeneratedCodeFunctionReuse_U.In1, GeneratedCodeFunctionReuse_U.In2, GeneratedCodeFunctionReuse_P.T2Data, GeneratedCodeFunctionReuse_P.T2Break, &GeneratedCodeFunctionReuse_B.SS2); /* End of Outputs for SubSystem: '<Root>/SS2' */ /* Outport: '<Root>/Out2' */ GeneratedCodeFunctionReuse_Y.Out2 = GeneratedCodeFunctionReuse_B.SS2.LookupTable; }
モデルのステップ関数に、再利用可能な関数 myfun
の呼び出しが 2 つあります。マスク パラメーター T1Break
、T1Data
、T2Break
および T2Data
は、関数の引数です。
[関数のパッケージ化] パラメーターを Inline
に変更します。
set_param('GeneratedCodeFunctionReuse/SS1','RTWSystemCode','Inline') set_param('GeneratedCodeFunctionReuse/SS2','RTWSystemCode','Inline')
コードを生成して検査します。
slbuild(model)
### Starting build procedure for: GeneratedCodeFunctionReuse ### Successful completion of build procedure for: GeneratedCodeFunctionReuse Build Summary Top model targets built: Model Action Rebuild Reason =========================================================================================== GeneratedCodeFunctionReuse Code generated and compiled. Generated code was out of date. 1 of 1 models built (0 models already up to date) Build duration: 0h 0m 7.4984s
cfile=fullfile(pwd, 'GeneratedCodeFunctionReuse_grt_rtw', 'GeneratedCodeFunctionReuse.c'); coder.example.extractLines(cfile, '/* Model step', '/* Model initialize', 1, 0);
/* Model step function */ void GeneratedCodeFunctionReuse_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 = GeneratedCodeFunctionReuse_U.In1 + GeneratedCodeFunctionReuse_U.In2; /* End of Outputs for SubSystem: '<Root>/SS2' */ /* Outport: '<Root>/Out1' incorporates: * Lookup_n-D: '<S1>/Lookup Table' * Sum: '<S1>/Sum' */ GeneratedCodeFunctionReuse_Y.Out1 = look1_binlx(Out1_tmp, GeneratedCodeFunctionReuse_P.T1Break, GeneratedCodeFunctionReuse_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' */ GeneratedCodeFunctionReuse_Y.Out2 = look1_binlx(Out1_tmp, GeneratedCodeFunctionReuse_P.T2Break, GeneratedCodeFunctionReuse_P.T2Data, 10U); /* End of Outputs for SubSystem: '<Root>/SS2' */ }
モデルのステップ関数では、サブシステム コードはインライン化されます。
[関数のパッケージ化] パラメーターを Nonreusable function
に変更します。SS2
の場合は、[関数名] パラメーターを myfun2
に変更します。
set_param('GeneratedCodeFunctionReuse/SS1','RTWSystemCode','Nonreusable function') set_param('GeneratedCodeFunctionReuse/SS2','RTWSystemCode','Nonreusable function') set_param('GeneratedCodeFunctionReuse/SS2','RTWFcnName','myfun2')
コードを生成して検査します。
slbuild(model)
### Starting build procedure for: GeneratedCodeFunctionReuse ### Successful completion of build procedure for: GeneratedCodeFunctionReuse Build Summary Top model targets built: Model Action Rebuild Reason =========================================================================================== GeneratedCodeFunctionReuse Code generated and compiled. Generated code was out of date. 1 of 1 models built (0 models already up to date) Build duration: 0h 0m 9.0245s
cfile=fullfile(pwd, 'GeneratedCodeFunctionReuse_grt_rtw', 'GeneratedCodeFunctionReuse.c'); coder.example.extractLines(cfile, '/* Model step', '/* Model initialize', 1, 0);
/* Model step function */ void GeneratedCodeFunctionReuse_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' */ }
モデルのステップ関数に、関数 myfun
と myfun2
の呼び出しが含まれています。これらの関数には void-void インターフェイスがあります。
[関数のパッケージ化] パラメーターを Auto
に変更します。
set_param('GeneratedCodeFunctionReuse/SS1','RTWSystemCode','Auto') set_param('GeneratedCodeFunctionReuse/SS2','RTWSystemCode','Auto')
auto
設定では、Simulink Coder は最適な形式を選択します。このモデルでは、最適な形式は再利用可能な関数です。
制限
サブシステムでのコードの再利用は最適化機能であり、保証されるものではありません。サブシステムでのコードの再利用に関する制限を次に示しますが、このリストがすべてを網羅しているとは限りません。
コード ジェネレーターはチェックサムを使用して、サブシステムが同一であり再利用可能であるかどうかを判断します。次の場合、サブシステム コードは再利用されません。
ブロックとデータ オブジェクトで、シンボルを使用して次元を指定している。
端子のサンプル時間、データ型、実数/複素数、フレーム ステータス、次元がサブシステムによって異なる。
サブシステムの出力がグローバル信号としてマークされている。
名前やパラメーター設定の異なる同一ブロックがサブシステムに含まれている。
サブシステムの出力が Merge ブロックに接続されていて、Merge ブロックの出力がアドレス指定できないメモリ (
BitField
など) として C コードに実装されるカスタム ストレージ クラスを使用して設定されている。サブシステムの入力が非スカラーで、アドレス指定できないメモリとして C コードに実装されるカスタム ストレージ クラスを使用して設定されている。
マスク サブシステムが非スカラーのパラメーターをもち、アドレス指定できないメモリとして C コードに実装されるカスタム ストレージ クラスを使用して設定されている。
モデル コンフィギュレーション パラメーターの既定のパラメーター動作を
[調整可能]
に設定した場合に、Function-Call Subsystem はマスク パラメーターを使用する。マスクされた Function-Call Subsystem を再利用するには、それを新しい Atomic Subsystem 内にマスクなしで配置します。次に、Trigger ブロックをマスク サブシステムから Atomic Subsystem に移動します。サブシステムのブロックは "部分的に調整可能な式" を使用する。部分的に調整可能な式によってはコードの再利用を無効にします。
モデル参照全体で再利用できるようにサブシステムを構成し、そのサブシステムに組み込みの S-Function が含まれている。
部分的に調整可能な式は、1 つ以上の調整可能な変数と調整不可能な式が含まれる式です。たとえば、値
15.23
をもつ調整可能な変数K
と、値[5;7;9]
をもつ調整可能な変数P
を作成すると仮定します。式P'
は調整不可能なので、式K+P'
は部分的に調整可能な式になります。調整可能な式の制限の詳細については、調整可能な式の制限を参照してください。
再利用可能な S-Function ブロックを含むサブシステムでは、ブロックはコード再利用のための S-Functionにリストされている要件を満たなければなりません。
[再利用可能な関数]
が選択されていて、コード ジェネレーターがサブシステムのコードが再利用できないと判断すると、再利用できない別の関数が生成されます。その関数が再利用可能かどうかは、それが 1 つのサブシステムだけで使用されている場合でも、コード生成レポートで確認できる可能性があります。(関数として導入するのではなく) このような場合のコード ジェネレーターのインライン サブシステム コードが必要な場合は、関数のパッケージ化を[自動]
に設定します。再利用可能なサブシステムで共有のローカル データ ストアを使用し、モデル データ要素に対して既定のマッピングを構成している場合は、カテゴリ [Shared local data stores] の既定のストレージ クラス マッピングを
[既定]
に設定したままにします。サブシステムにおける次のブロックの使用は、サブシステム コードの再利用を妨げる場合があります。
Scope ブロック (データ ログが有効化されている)
一定基準を満たさない S-Function ブロック (コード再利用のための S-Functionを参照)
To File ブロック (データ ログが有効化されている)
To Workspace ブロック (データ ログが有効化されている)
再利用可能なライブラリ サブシステム (参照モデル間で共有されるサブシステム) の場合、コード ジェネレーターは再利用可能なライブラリ サブシステム コードを共有ユーティリティ フォルダーに配置します。再利用可能なコードは最上位モデルや参照モデルの生成コードからは独立しています。たとえば、再利用可能なライブラリ サブシステム コードは
やmodel
.h
は含みません。model
_types.hコード ジェネレーターが共有ユーティリティ フォルダーに置き、かつモデル コード依存である再利用可能コードはコンパイルされません。コード ジェネレーターによって、再利用可能なライブラリ サブシステム コードがモデル コード依存であると判別されると、その再利用可能なサブシステム コードは共有ユーティリティ フォルダーに配置されません。再利用可能なライブラリ サブシステムが次の場合、コード ジェネレーターはモデル コード依存のコードを生成します:
Step ブロック、連続時間またはマルチレート ブロックなど、時間関連の機能を使用するブロックを含む
1 つ以上の Model ブロックを含む
インライン化されていないサブシステムまたは再利用可能なライブラリ サブシステムを含む
データ宣言を
model_ert_rtw
にあるファイルに配置するストレージ クラスをもつ信号またはパラメーターを含む (たとえば、ExportedGlobal
ストレージ クラスはデータをmodel.c
に配置)。Enumeration、Simulink.Signal、Simulink.Parameter など、[データ スコープ] が
[エクスポート]
に設定されていないユーザー定義ストレージ クラスを含む。コード ジェネレーターは型定義を
に配置している場合があります。model
_types.hプリプロセッサ条件を生成する Variant Subsystem である。コード ジェネレーターはバリアント オブジェクトを定義するプリプロセッサ命令を
に配置します。model
_types.h
コード ジェネレーターは、
[なし]
以外のメモリ セクションを使用する定数の既定のマッピングを指定するモデルについては、再利用可能なライブラリ サブシステム コードを生成しません。モデルに同じサブシステムのインスタンスが複数あり、一方のサブシステムは Constant ブロックに接続されてもう一方は接続されていない場合、サブシステムを再利用できません。この制限を回避するには、サブシステムの前に Signal Conversion ブロックを挿入します。
チェックサムが異なる 2 つの再利用可能なサブシステムでは、生成コードで同じ関数を共有できません。[ブロック パラメーター (Subsystem)] 、 [コード生成] 、 [関数名] で両方のサブシステムに同じ関数名を指定すると、次のようになります。
サブシステムがライブラリにリンクされている場合、コード ジェネレーターは関数名をマングルして一意の関数名を生成します。コード ジェネレーターによる関数名の生成にはサブシステムの命名規則が使用されます。
サブシステムがライブラリにリンクされていない場合、コード ジェネレーターはエラーを発行します。
上記の制限はライブラリベースのコード生成にも適用されます。詳細については、Library-Based Code Generation for Reusable Library Subsystems (Embedded Coder)を参照してください。