Main Content

TLC カバレッジ

TLC カバレッジ オプションの使用

TLC デバッガーの使用の例では、デバッガーを使用して TLC ファイルの 1 つのセクションで問題を検出しました。テスト モデルでは可能性があるすべてのケースがカバーされないことがあるため、TLC カバレッジ オプションという未テストのケースをトレースする手法が用意されています。

TLC カバレッジ オプションは、コード内のそれぞれのコード部分 (パスではない) が実行されたことをより簡単に確認する方法を提供します。TLC カバレッジの追跡を指定するには、[コンフィギュレーション パラメーター] ダイアログ ボックスでStart TLC coverage when generating codeを選択します。

TLC カバレッジを開始すると、使用された各ターゲット ファイル (*.tlc) について、Target Language Compiler で .log ファイルが生成されます。これらの .log ファイルは、モデル用に作成されたプロジェクト フォルダーに配置されます。各 .log ファイルには、実行時にそれぞれの行が何回実行されたかを示す使用状況 (カウント) の情報が格納されます。各行の先頭に実行回数が記載され、その後にコロンで区切ってコードが続きます。

.log ファイルの例

次に、モデル例 sfcndemo_sdotproduct のコード生成結果のログ ファイルを示します。このモデルはフォルダー matlabroot/toolbox/simulink/simdemos/simfeatures (開く) にあります。このモデルでは TLC で sdotproduct S-Function をインライン化しています。S-Function を実装する TLC ファイルは、フォルダー matlabroot/toolbox/simulink/sfuntemplates/tlc_c (開く) にあります。sdotproduct.tlc.log ファイルは sdotproduct.log で、ビルド フォルダーに配置されます。sdotproduct.log の内容は次のようになります。

Source: E:\matlab\toolbox\simulink\sfuntemplates\tlc_c\sdotproduct.tlc
 0: %% 
 0: %% File : sdotproduct.tlc generated from sdotproduct.ttlc revision 1.6
 0: %%
 0: %% Abstract:
 0: %%      Dot product block target file.
 1: 
 1: %implements sdotproduct "C"
 1: 
 0: %% Function: FcnThriftedComplexMultiply 
========================================
 0: %% Abstract:
 0: %%      This function multiplies two numbers in the complex plane. If any of
 0: %%      the input arguments is only real, then the complex part is passed in
 0: %%      as "".
 0: %%
 1: %function FcnThriftedComplexConjMultiply(ar,ai,br,bi,cr,ci,op) void
 2:   %openfile buffer
 0:   %%
 0:   %% Compute Cr = Ar * Br + Ai * Bi
 0:   %%
 2:   %assign rhsStr = "%<ar> * %<br>"
 2:   %if !LibIsEqual(ai, "") && !LibIsEqual(bi, "")
 0:     %assign rhsStr = rhsStr + " + %<ai> * %<bi>"
 0:   %endif
 2:   %<cr> %<op> %<rhsStr>;
 0:   %%
 0:   %% Compute Ci = Ar * Bi - Ai * Br
 0:   %%
 2:   %if !LibIsEqual(ci, "")
 0:     %assign rhsStr = "0.0"
 0:     %if !LibIsEqual(bi, "")
 0:       %assign rhsStr = "%<ar> * %<bi>"
 0:     %endif
 0:     %if !LibIsEqual(ai, "")
 0:       %assign rhsStr = rhsStr + " - %<ai> * %<br>"
 0:     %endif
 0:     %<ci> %<op> %<rhsStr>;
 0:   %endif
 0:   %%
 2:   %closefile buffer
 2:   %return buffer
 0: %endfunction %% FcnThriftedComplexMultiply
 1: 
 1: 
 0: %% Function: Outputs 
===========================================================
 0: %% Abstract:
 0: %%      Y = U0' * U1, where U0' is the complex conjugate transpose of U0
 0: %%
 1: %function Outputs(block, system) Output
 1:   %assign sfcnName = ParamSettings.FunctionName
 1:   /* %<Type> Block (%<sfcnName>): %<LibParentMaskBlockName(block)> */
 0:   %%
 1:   %assign u0re = LibBlockInputSignal(0, "", "", "%<tRealPart>0")
 1:   %assign u0im = LibBlockInputSignal(0, "", "", "%<tImagPart>0")
 1:   %assign u1re = LibBlockInputSignal(1, "", "", "%<tRealPart>0")
 1:   %assign u1im = LibBlockInputSignal(1, "", "", "%<tImagPart>0")
 0:   %%
 1:   %assign yre = LibBlockOutputSignal(0, "", "", "%<tRealPart>0")
 1:   %assign yim = LibBlockOutputSignal(0, "", "", "%<tImagPart>0")
 0:   %%
 0:   %% Need to declare a temporary variable for u1re when the output is
 0:   %% being overwritten and u0im is nonzero
 1:   %assign outputOverWritesInput = ...
 0:     ((LibBlockInputSignalBufferDstPort(0) == 0) || ...
 0:      (LibBlockInputSignalBufferDstPort(1) == 0)) &&   ...
 0:     (LibBlockInputSignalIsComplex(0) && LibBlockInputSignalIsComplex(1))
 0:   %%
 1:   %if outputOverWritesInput
 0:     {
 0:       %assign dtName = LibBlockOutputSignalDataTypeName(0, tRealPart)
 0:       %<dtName> tmpVar;
 0:     \
 0:     %assign tmpVar = "tmpVar"
 0:   %else
 1:     %assign tmpVar = yre
 0:   %endif
 0:   %%
 1:   %<FcnThriftedComplexConjMultiply(u0re, u0im, u1re, u1im, tmpVar, yim, "=")>\
 0:   %%
 1:   %assign rollVars    = ["U", "Y"]
 1:   %assign rollRegion  = LibGetRollRegions1(RollRegions)
 0:   %%
 1:   %if LibIsEqual(rollRegion, []) 
 0:     %if outputOverWritesInput
 0:       %<yre> = tmpVar;
 0:     %endif
 0:   %else
 0:     %% Continue with dot product for nonscalar case
 1:     %roll idx = rollRegion, lcv = RollThreshold, block, "Roller", rollVars
 1:       %assign u0re = LibBlockInputSignal(0,"",lcv,"%<tRealPart>%<idx>")
 1:       %assign u0im = LibBlockInputSignal(0,"",lcv,"%<tImagPart>%<idx>")
 1:       %assign u1re = LibBlockInputSignal(1,"",lcv,"%<tRealPart>%<idx>")
 1:       %assign u1im = LibBlockInputSignal(1,"",lcv,"%<tImagPart>%<idx>")
 0:       %%			   
 1:       %assign yre = LibBlockOutputSignal(0,"",lcv,"%<tRealPart>%<idx>")
 1:       %assign yim = LibBlockOutputSignal(0,"",lcv,"%<tImagPart>%<idx>")
 0:       %%
 1:       %<FcnThriftedComplexConjMultiply(u0re, u0im, u1re, u1im, yre, yim, "+=")>\
 0:     %endroll
 0:   %endif
 1:   %if outputOverWritesInput
 0:     }
 0:   %endif
 1: 
 0: %endfunction
 1: 
 0: %% [EOF] sdotproduct.tlc

結果の解析

この構造により、実行されていない分岐を簡単に特定し、ターゲット ファイルの未使用部分を実行できる新しいテストを開発できます。

sdotproduct.log ファイルを確認すると、パラメーターに既定値を割り当てるコード (関数 FcnThriftedComplexConjMultiply のコードの最初の部分など) が使用されていないことがわかります。このログを参考にして未実行の行を実行するモデルを作成することで、よりロバストなコードにすることができます。

関連するトピック