S-Function のインライン化
S-Function のインライン化
S-Function のインライン化とは、S-Function ブロックの TLC ファイルを用意して、シミュレーションで使用された C、C++、Fortran、または MATLAB® 言語バージョンのブロックと置き換えることを意味します。
インラインでない S-Function
インライン化された TLC ファイルが提供されない場合、ほとんどのターゲットでは、ブロックの C MEX S-Function を再コンパイルすることでブロックをサポートします。前述のとおり、C/C++ コードで記述された S-Function を使用する場合はメモリ使用量と速度にオーバーヘッドがあり、コード ジェネレーターのコンテキストで mx*
API 呼び出しの限られたサブセットしかサポートされません。最も効率的な生成コードにするには、TLC ファイルを記述して S-Function をインライン化する必要があります。
シミュレーションで S-Function ブロックの関数のいずれかを実行する必要がある場合、その関数の MEX ファイルが呼び出されます。インラインでない S-Function をコード ジェネレーターで実行するときも、次の図に示すように、これと同じように処理されます。
インライン化のタイプ
インライン化については、2 つのカテゴリに分けて考えると便利です。
完全インライン化 S-Function
ラッパー インライン化 S-Function
どちらも S-Function をインライン化し、インラインでない S-Function のオーバーヘッドを排除しますが、そのアプローチが異なります。以下の timestwo.tlc
を使用する 1 つ目の例では、ブロックの TLC ファイルにブロックの完全な実装が含まれており、完全にインライン化された TLC ファイルと見なされます。
2 つ目の例ではラッパー TLC ファイルを使用します。この例では、アルゴリズム コードを生成して配置する代わりに、コードの本体を含む C 関数を呼び出しています。ラッパー TLC ファイルを使用する利点としては、次のようなことが考えられます。
C MEX S-Function と生成コードで C コードを共有する手段が提供される。コードを 2 回記述する必要がない。
C 関数として最適化されたルーチンが呼び出される。
ブロックがモデル内に複数存在している可能性があり、それらで関数を呼び出した方が、それぞれで同じアルゴリズム コードを作成するよりもコード サイズの点で効率的である。
レガシ C コードを生成コードにシームレスに組み込む手段が提供される。
完全インライン化 S-Function の例
S-Function をインライン化することで、S-Function ブロックのコードをモデルの生成コードに直接組み込むメカニズムが提供されます。関数ポインターで個別のソース ファイルを呼び出してそれに対する個別のデータ構造体 (SimStruct
) を維持する代わりに、コードが次の図に示すように "インライン化" されて表示されます。
S-Function timestwo.c
は、完全インライン化 S-Function の簡単な例を提供します。このブロックは入力を 2 倍にして出力します。C MEX バージョンのブロックはファイル
にあります。このブロックのインライン化された TLC ファイルが matlabroot
/toolbox/simulink/simdemos/simfeatures/src/timestwo.c
です。matlabroot
/toolbox/simulink/simdemos/simfeatures/tlc_c/timestwo.tlc
timestwo.tlc
%implements "timestwo" "C" %% Function: Outputs ========================================== %% %function Outputs(block, system) Output /* %<Type> Block: %<Name> */ %% /* Multiply input by two */ %assign rollVars = ["U", "Y"] %roll idx = RollRegions, lcv = RollThreshold, block, "Roller", rollVars %<LibBlockOutputSignal(0, "", lcv, idx)> = \ %<LibBlockInputSignal(0, "", lcv, idx)> * 2.0; %endroll %endfunction
TLC ブロックの解析
%implements
命令は、TLC ブロック ファイルに必須の命令です。ブロックでサポートされるブロック タイプと言語を確認するために Target Language Compiler で使用されます。%function
命令から関数宣言が始まります。関数の名前 Outputs
とそれに渡す引数 block
および system
が表示されています。これらは、ブロックのこのインスタンスに対する
ファイルからの関連レコードです。model
.rtw
プロトタイプの最後に Output
という部分があります。これは、TLC で選択されている現在のファイルに TLC 命令でないすべての行を関数で出力することを意味します。したがって、関数 Outputs
の命令以外の行がブロックの生成コードになります。
この TLC ブロックの例で最も複雑なのは %roll
命令の部分です。TLC では、この命令を使用して for
ループの自動生成を提供します。これは、入力/出力の幅や入力がメモリ内で連続しているかどうかに依存します。この例では、ロール本体の内部から出力と入力にアクセスする標準の形式を使用しており、LibBlockOutputSignal
と LibBlockInputSignal
を使用して出力と入力にアクセスし、乗算と代入を実行しています。この TLC ファイルでは任意の有効な信号の幅がサポートされることに注意してください。
このブロックの実装に使用されている関数は Outputs
だけです。より複雑なブロックでは、他の関数も宣言されます。より複雑なインライン化された TLC ファイルの例は、フォルダー
(開く) および matlabroot
/toolbox/simulink/simdemos/simfeatures/tlc_c
(開く) にあります。組み込みブロックのコードについては、フォルダー matlabroot
/toolbox/simulink/blocks/tlc_c
(開く) を参照してください。matlabroot/rtw/c/tlc/blocks
timestwo モデル
この簡単なモデルでは、timestwo
S-Function を使用し、生成された
ファイルから関数 model
.cMdlOutputs
を表示します。これに、インライン化 S-Function のコードが含まれています。
モデルの出力のコード
/* Model output function */ static void timestwo_ex_output(int_T tid) { /* S-Function Block: <Root>/S-Function */ /* Multiply input by two */ timestwo_ex_B.timestwo_output = timestwo_ex_P.Constant_Value * 2.0; /* Outport: '<Root>/Out1' */ timestwo_ex_Y.Out1 = timestwo_ex_B.timestwo_output; }
ラッパー インライン化 S-Function の例
次の図は、S-Function をラッパーとしてインライン化する場合を示しています。アルゴリズムが生成されたモデル コードから直接呼び出され、S-Function のオーバーヘッドが排除されていますが、ユーザー関数は維持されています。
timestwo
ブロックのラッパー バージョンのインライン化された TLC ファイルは次のとおりです。
%implements "timestwo" "C" %% Function: BlockTypeSetup ================================== %% %function BlockTypeSetup(block, system) void %% Add function prototype to model's header file %<LibCacheFunctionPrototype... ("extern void mytimestwo(real_T* in,real_T* out,int_T els);")> %% Add file that contains "myfile" to list of files to be compiled %<LibAddToModelSources("myfile")> %endfunction %% Function: Outputs ========================================== %% %function Outputs(block, system) Output /* %<Type> Block: %<Name> */ %assign outPtr = LibBlockOutputSignalAddr(0, "", "", 0) %assign inPtr = LibBlockInputSignalAddr(0, "", "",0) %assign numEls = LibBlockOutputSignalWidth(0) /* Multiply input by two */ mytimestwo(%<inPtr>,%<outPtr>,%<numEls>); %endfunction
解析
関数 BlockTypeSetup
は、モデル内のブロックのタイプごとに 1 回呼び出されます。関数 Outputs
のように出力を直接生成することはありません。BlockTypeSetup
を使用して、関数プロトタイプを
ファイルに含め、ビルド プロセスで追加ファイル model
.hmyfile.c
をコンパイルするように指示します。
ここでは、乗算を直接実行する代わりに、関数 Outputs
で関数 mytimestwo
を呼び出しています。モデル内のこのブロックのすべてのインスタンスが同じ関数を呼び出して乗算を実行します。結果のモデルの関数 MdlOutputs
は次のようになります。
static void timestwo_ex_output(int_T tid) { /* S-Function Block: <Root>/S-Function */ /* Multiply input by two */ mytimestwo(&model_B.Constant_Value,&model_B.S_Function,1); /* Outport Block: <Root>/Out1 */ model_Y.Out1 = model_B.S_Function; }