このページの内容は最新ではありません。最新版の英語を参照するには、ここをクリックします。
TLC コードのデバッグ
tlcdebug
チュートリアルの概要
目的: TLC デバッガーを紹介します。ブレークポイントを設定する方法を学習し、TLC デバッガー コマンドを理解します。
次の例を開きます。
openExample('simulinkcoder/AdviceAboutTLCTutorialsExample')
cd(tlctutorial/tlcdebug)
ビルド プロセスが呼び出されるごとに TLC デバッガーが呼び出されるようにすることができます。このチュートリアルでは、これを使用して、simple_log
というモデルの .tlc
ファイル内のバグを検出します。このバグにより、モデルのスタンドアロン バージョンから出力される生成コードがシミュレーション出力と異なるものになっています。このチュートリアルでは、以下の手順を順を追って説明します。
入門 — モデルを実行して出力を検査
モデルからのコードの生成と実行 — コンパイル済みの結果を元の出力と比較
デバッガーの開始とそのコマンドの使用 — デバッガーで行える処理
デバッグ
timesN.tlc
— 問題を特定バグの修正と確認 — バグを修正して修正を確認する簡単な方法
入門
MATLAB® コマンド ウィンドウで、S-Function の MEX ファイルを作成します。
mex timesN.c
これにより、Simulink® ソフトウェアに付属しているバージョンが選択されなくなります。
メモ
まだ
mex -setup
を実行していない場合は、エラーが発生することがあります。モデル
simple_log
を開きます。モデルは次のとおりです。[コンフィギュレーション パラメーター] ダイアログ ボックスの [データのインポート/エクスポート] ペインで、[時間] および [出力] をオンにします。これにより、モデル変数が MATLAB ワークスペースに記録されます。
モデルを実行します。[シミュレーション] タブで [実行] をクリックします。変数
tout
とyout
が MATLAB ワークスペースに表示されます。MATLAB コマンド ウィンドウの [ワークスペース] ペインの
yout
をダブルクリックします。変数エディターでsimple_log
から出力された 6 行 1 列の配列が表示されます。以下のような表示になります。列 1 には、端子
out1
で収集された、6 つのタイム ステップの離散パルス出力 (3s と 0s) が含まれています。
次に、simple_log
のスタンドアロン バージョンを生成します。それを実行し、結果を上に表示されている Simulink からの出力と比較します。
メモ
この演習のために、提供されている TLC ファイル timesN.tlc
にはバグが含まれています。このバージョンは、それを使用しているモデルと同じフォルダーに配置されている必要があります。
モデルからのコードの生成と実行
Ctrl+B キーを押します。
コード ジェネレーターにより、C ソース コードが生成、コンパイル、リンクされます。MATLAB コマンド ウィンドウにビルドの進行状況が表示され、その最後に以下のメッセージが示されます。
### Created executable: simple_log.exe ### Successful completion of build procedure for model: simple_log
以下を入力して、作成したスタンドアロン モデルを実行します。
!simple_log
これにより、以下のメッセージが表示されます。
** starting the model ** ** created simple_log.mat **
ワークスペースに変数を配置して結果を検査します。[現在のフォルダー] ペインで
simple_log.mat
をダブルクリックしてから、[ワークスペース] ペインのrt_yout
(変数yout
のスタンドアロン バージョン) をダブルクリックします。rt_yout
をyout
と比較します。差異を確認します。rt_yout
の値が変化した原因を考えます。TLC でビルド フォルダー (
simple_log_grt_rtw
) に配置された、生成された C コードを見れば、問題の特定に役立ちます。simple_log.c
を編集し、その関数MdlOutputs
を確認します。以下に示されているようになっています。/* Model output function */ static void simple_log_output(void) { /* DiscretePulseGenerator: '<Root>/Discrete Pulse Generator' */ simple_log_B.DiscretePulseGenerator = (simple_log_DW.clockTickCounter < 1.0) && (simple_log_DW.clockTickCounter >= 0) ? 1.0 : 0.0; if (simple_log_DW.clockTickCounter >= 2.0 - 1.0) { simple_log_DW.clockTickCounter = 0; } else { simple_log_DW.clockTickCounter++; } /* End of DiscretePulseGenerator: '<Root>/Discrete Pulse Generator' */ /* S-Function (timesN): '<Root>/Gain1st' incorporates: * Outport: '<Root>/Out1' */ /* S-Function Block: <Root>/Gain1st */ /* Multiply input by 3.0 */ simple_log_Y.Out1 = simple_log_B.DiscretePulseGenerator * 1; }
最後の方にある以下の行に注意してください。
simple_log_B.first_output = simple_log_B.DiscretePulseGenerator * 1;
デバッガーの開始とそのコマンドの使用
TLC デバッガーを使用してコード生成プロセスを監視します。既定では呼び出されないため、デバッガーを明示的に要求する必要があります。
TLC デバッグ環境を設定し、アプリケーションのビルドを開始します。
[コンフィギュレーション パラメーター] 、 [コード生成] ペインを選択し、オプション [.rtw ファイルを残す] および [コード生成時に TLC デバッガーを実行] を選択します。[OK] をクリックします。
モデルをビルドします。
MATLAB コマンド ウィンドウでビルド プロセスが記述されます。ビルドは
timesN.tlc
ファイルで停止し、コマンド プロンプトが表示されます。TLC-DEBUG>
「
help
」と入力して TLC デバッガー コマンドのリストを表示します。以下にデバッガーでできることをいくつか示します。TLC スコープの各種エンティティを表示およびクエリする。
TLC-DEBUG> whos CompiledModel TLC-DEBUG> print CompiledModel.NumSystems TLC-DEBUG> print TYPE(CompiledModel.NumSystems)
現在のコンテキストでステートメントを調べる。
TLC-DEBUG> list TLC-DEBUG> list 10,40
次のコード行に移動する。
TLC-DEBUG> next
関数にステップインする。
TLC-DEBUG> step
入力信号
%<u>
など、変数に定数値を代入する。TLC-DEBUG> assign u = 5.0
現在の位置またはコードの他の部分にブレークポイントを設定する。
TLC-DEBUG> break timesN.tlc:10
次のブレークポイントまで実行する。
TLC-DEBUG> continue
設定したブレークポイントをクリアする。
TLC-DEBUG> clear 1 TLC-DEBUG> clear all
TLC デバッガー コマンドを試した場合、残りのコードを実行してビルド プロセスを完了してから、
simple_log
を再度ビルドします。ビルドはtimesN.tlc
ファイルで停止し、コマンド プロンプトが表示されます。TLC-DEBUG>
timesN.tlc
のデバッグ
次に、コードの問題の原因を調べて特定します。
timesN.tlc
の 20 行目にブレークポイントを設定します。TLC-DEBUG> break timesN.tlc:20
ブレークポイントまで進むように TLC デバッガーに指示します。
TLC-DEBUG> continue
TLC は入力を処理し、進行状況をレポートして、
timesN.tlc
の 20 行目まで進んでその行を表示してから、一時停止します。### Loading TLC function libraries ... ### Initial pass through model to cache user defined code . ### Caching model source code . Breakpoint 1 00020: %roll idx = RollRegions, lcv = RollThreshold, block, "Roller", rollVars
whos
コマンドを使用して現在のスコープの変数を確認します。TLC-DEBUG> whos Variables within: <BLOCK_LOCAL> gain Real rollVars Vector block Resolved system Resolved
print コマンドを使用して変数を検査します (名前では大文字と小文字が区別されます)。
TLC-DEBUG> print gain 3.0 TLC-DEBUG> print rollVars [U, Y]
1 ステップ実行します。
TLC-DEBUG> step 00021: %<LibBlockOutputSignal(0, "", lcv, idx)> = \
組み込み関数であるため、
next
コマンドを使用して先に進めます。TLC-DEBUG> next . 00022: %<LibBlockInputSignal(0, "", lcv, idx)> * 1;
これが、間違った定数出力
simple_log_B.first_output = simple_log_B.DiscretePulseGenerator * 1;
の原因となった C ステートメントの起点です。TLC デバッガーを終了してビルドを破棄します。以下を入力します。
TLC-DEBUG> quit
エラー メッセージが表示され、TLC デバッガーの
quit
コマンドを使用してビルドを停止したことが示されます。エラー ウィンドウを閉じます。
バグの修正と確認
特定した問題の原因は、TLC 関数 FcnEliminateUnnecessaryParams()
内で変数ではなく定数を評価していることです。これは典型的なコーディング エラーであり、簡単に修正できます。以下に修正する必要のあるコードを示します。
%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)> * 1; %endroll %endfunction %% [EOF] timesN.tlc
コーディング エラーを修正するには、
timesN.tlc
を編集します。以下の行では評価された入力に 1 を乗算しています。この行を以下に変更します。%<LibBlockInputSignal(0, "", lcv, idx)> * 1;
%<LibBlockInputSignal(0, "", lcv, idx)> * %<gain>;
timesN.tlc
を保存します。スタンドアロン モデルを再度ビルドします。各
TLC-DEBUG>
プロンプトで「continue
」と入力してビルドを完了します。以下を入力して、スタンドアロン モデルを実行します。
!simple_log
simple_log.mat
の新しいバージョンが作成され、その出力が含まれます。前と同様に、
simple_log.mat
を読み込んでワークスペース変数rt_yout
をyout
と比較します。これで、最初の列の値が同じになっています。