このページの内容は最新ではありません。最新版の英語を参照するには、ここをクリックします。
変数名およびループ ローリングの探索
timesN
ループ チュートリアルの概要
目的: この例では、生成コードのループ動作を変更する方法について説明します。
次の例を開きます。
openExample('simulinkcoder/AdviceAboutTLCTutorialsExample') cd('tlctutorial/timesN')
tlctutorial/timesN
でモデル sfun_xN
を操作します。1 つのソース (Sine Wave ジェネレーター ブロック)、times N ゲイン ブロック、Out ブロック、および Scope ブロックがあります。
このチュートリアルでは、以下の手順を順を追って説明します。
入門 — 演習を設定してモデルを実行
モデルの変更 — 入力幅を変更して結果を確認
ループ ローリングしきい値の変更 — しきい値を変更して結果を確認
TLC ループ ローリングの詳細 — ループ動作をパラメーター化
入門
tlctutorial/timesN
を現在のフォルダーにし、提供されているファイルを使用できるようにします。MATLAB® コマンド ウィンドウで、S-Function の MEX ファイルを作成します。
mex timesN.c
これにより、Simulink® に付属しているバージョンが選択されなくなります。
メモ
まだ
mex -setup
を実行していない場合は、エラーが発生することがあります。モデル ファイル
sfun_xN
を開きます。sfun_xN_grt_rtw/sfun_xN.c
にある以前に生成されたコードを表示します。ループがコードに存在していないことに注意します。これは、入出力信号がスカラーであるためです。
モデルの変更
Sine Wave ブロックを Constant ブロックに置き換えます。
Constant ブロックのパラメーターを 1:4 に設定し、上のラベル
model: sfun_xN
をmodel: sfun_vec
に変更します。編集したモデルを (
tlctutorial/timesN
内の)sfun_vec
として保存します。これで、モデルは次のようになります。Constant ブロックで値のベクトルが生成されるため、これはベクトル化モデルです。モデルのコードを生成し、エディターで
sfun_vec.c
の/*Model output function */
セクションを表示して、変数およびfor
ループがどのように処理されるのかを観察します。この関数は以下のように表示されます。/* Model output function */ static void sfun_vec_output(int_T tid) { /* S-Function Block: <Root>/S-Function */ /* Multiply input by 3.0 */ sfun_vec_B.timesN_output[0] = sfun_vec_P.Constant_Value[0] * 3.0; sfun_vec_B.timesN_output[1] = sfun_vec_P.Constant_Value[1] * 3.0; sfun_vec_B.timesN_output[2] = sfun_vec_P.Constant_Value[2] * 3.0; sfun_vec_B.timesN_output[3] = sfun_vec_P.Constant_Value[3] * 3.0; /* Outport: '<Root>/Out' */ sfun_vec_Y.Out[0] = sfun_vec_B.timesN_output[0]; sfun_vec_Y.Out[1] = sfun_vec_B.timesN_output[1]; sfun_vec_Y.Out[2] = sfun_vec_B.timesN_output[2]; sfun_vec_Y.Out[3] = sfun_vec_B.timesN_output[3]; UNUSED_PARAMETER(tid); }
モデル出力を生成するコードのインスタンスが 4 つあり、4 回の反復に対応していることに注意します。
Constant ブロックのパラメーターを 1:10 に設定し、モデルを保存します。
モデルのコードを生成し、エディターで
sfun_vec.c
の/*Model output function */
セクションを表示して、変数およびfor
ループがどのように処理されるのかを観察します。この関数は以下のように表示されます。/* Model output function */ static void sfun_vec_output(int_T tid) { /* S-Function Block: <Root>/S-Function */ /* Multiply input by 3.0 */ { int_T i1; const real_T *u0 = &sfun_vec_P.Constant_Value[0]; real_T *y0 = sfun_vec_B.timesN_output; for (i1=0; i1 < 10; i1++) { y0[i1] = u0[i1] * 3.0; } } { int32_T i; for (i = 0; i < 10; i++) { /* Outport: '<Root>/Out' */ sfun_vec_Y.Out[i] = sfun_vec_B.timesN_output[i]; } } UNUSED_PARAMETER(tid); }
次の点に注意してください。
モデル出力を生成するコードがループに "ロール" されます。既定では、これは反復回数が 5 回を超えると行われます。
ループのインデックス
i1
は 0 から 9 までです。ポインター
*y0
が使用され、出力信号配列に初期化されます。
ループ ローリングしきい値の変更
コード ジェネレーターは、[ループ展開のしきい値] パラメーターの現在の値に応じて反復またはループを作成します。
[ループ展開のしきい値] の既定値は 5
です。モデル内のブロックのループ動作を変更するには、以下のようにします。
[コンフィギュレーション パラメーター] ダイアログ ボックスの [最適化] ペインで、[ループ展開のしきい値] を
12
に設定し、Apply
をクリックします。パラメーター
RollThreshold
は12
になりました。ループが生成されるのは、ブロックを通過する信号の幅が 12 を超えている場合のみです。メモ
[コンフィギュレーション パラメーター] ダイアログ ボックスから特定のブロックの
RollThreshold
を変更することはできません。Ctrl+B を押して出力を再生成します。
sfun_vec.c
を検査します。次のようになります。/* Model output function */ static void sfun_vec_output(int_T tid) { /* S-Function Block: <Root>/S-Function */ /* Multiply input by 3.0 */ sfun_vec_B.timesN_output[0] = sfun_vec_P.Constant_Value[0] * 3.0; sfun_vec_B.timesN_output[1] = sfun_vec_P.Constant_Value[1] * 3.0; sfun_vec_B.timesN_output[2] = sfun_vec_P.Constant_Value[2] * 3.0; sfun_vec_B.timesN_output[3] = sfun_vec_P.Constant_Value[3] * 3.0; sfun_vec_B.timesN_output[4] = sfun_vec_P.Constant_Value[4] * 3.0; sfun_vec_B.timesN_output[5] = sfun_vec_P.Constant_Value[5] * 3.0; sfun_vec_B.timesN_output[6] = sfun_vec_P.Constant_Value[6] * 3.0; sfun_vec_B.timesN_output[7] = sfun_vec_P.Constant_Value[7] * 3.0; sfun_vec_B.timesN_output[8] = sfun_vec_P.Constant_Value[8] * 3.0; sfun_vec_B.timesN_output[9] = sfun_vec_P.Constant_Value[9] * 3.0; /* Outport: '<Root>/Out' */ sfun_vec_Y.Out[0] = sfun_vec_B.timesN_output[0]; sfun_vec_Y.Out[1] = sfun_vec_B.timesN_output[1]; sfun_vec_Y.Out[2] = sfun_vec_B.timesN_output[2]; sfun_vec_Y.Out[3] = sfun_vec_B.timesN_output[3]; sfun_vec_Y.Out[4] = sfun_vec_B.timesN_output[4]; sfun_vec_Y.Out[5] = sfun_vec_B.timesN_output[5]; sfun_vec_Y.Out[6] = sfun_vec_B.timesN_output[6]; sfun_vec_Y.Out[7] = sfun_vec_B.timesN_output[7]; sfun_vec_Y.Out[8] = sfun_vec_B.timesN_output[8]; sfun_vec_Y.Out[9] = sfun_vec_B.timesN_output[9]; UNUSED_PARAMETER(tid); }
ループ ローリングを再度有効にするには、[最適化] ペインで [ループ展開のしきい値] を 10 以下に変更します。
ループ ローリングは、生成コードを最適化するための重要な TLC 機能です。時間をとってその影響を調査、探索してから、量産要件向けのコードを生成してください。
TLC ループ ローリングの詳細
次の TLC %roll
コードは timesN.tlc
の関数 Outputs
です。
%function Outputs(block, system) Output /* %<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 %% Outputs
%roll
の引数
%roll
と %endroll
の間の行は繰り返すか、ループにすることができます。%roll
命令の理解の鍵は、その引数にあります。
%roll sigIdx = RollRegions, lcv = RollThreshold, block, "Roller", rollVars
引数 | 説明 |
---|---|
sigIdx | 生成コードで使用される (信号) ベクトルのインデックスを指定します。信号がスカラーの場合、 |
lcv |
|
block | これは、ブロック オブジェクトに対して操作するように TLC に指示します。S-Function 用の TLC コードはこの引数を使用します。 |
"Roller" | これは |
rollVars | ロールする項目のタイプ (入力信号、出力信号、またはパラメーター、あるいはその組み合わせ) を TLC に指示します。すべてを使用する必要はありません。前の行で、 %assign rollVars = ["U", "Y"] U ) および出力信号 (Y ) をロールすることを TLC に指示します。ブロックでスカラー パラメーターではなくパラメーターの配列が指定される場合は、rollvars は以下のように指定されます。%assign rollVars = ["U", "Y", "P"] |
入力信号、出力信号、およびパラメーター
%roll
と %endroll
の間にある行を見てみましょう。
%<LibBlockOutputSignal(0, "", lcv, idx)> = \ %<LibBlockInputSignal (0, "", lcv, idx)> * 2.0;
TLC ライブラリ関数 LibBlockInputSignal
および LibBlockOutputSignal
が展開され、名前とインデックスが付けられたスカラーまたはベクトル識別子が生成されます。LibBlockInputSignal
、LibBlockOutputSignal
、および多くの関連 TLC 関数には以下の 4 つの正準引数が渡されます。
引数 | 説明 |
---|---|
最初の引数 — | 所定のブロックの入力端子インデックスに対応しています。最初の入力端子のインデックスは 0 です。2 番目の入力端子のインデックスは 1 で、以下同様に続きます。 |
2 番目の引数 — | 高度な用途のために予約されているインデックス変数。ここでは、2 番目の引数は空 string として指定します。高度な用途では、 |
3 番目の引数 — | 前述のとおり、 |
4 番目の引数 — | TLC で特殊ケースを処理できるようにします。 |