このページの内容は最新ではありません。最新版の英語を参照するには、ここをクリックします。
C Caller ブロックおよび Stateflow チャート内のカスタム コードに対する Polyspace 解析の実行
Simulink® モデルで使用されるカスタム C/C++ コードのバグやランタイム エラーをチェックすることができます。Polyspace® 解析では、C Caller ブロックおよび Stateflow® チャートから呼び出された関数をモデルからの入力を使用してチェックします。
前提条件
Simulink から Polyspace を実行する前に、Polyspace インストールと MATLAB® インストールをリンクしなければなりません。MATLAB や Simulink との Polyspace の統合を参照してください。
この例で使用されるモデルを開くには、PolyspaceCode Prover™ ドキュメンテーションでこの例を検索し、[コマンドのコピー] ボタンをクリックして、MATLAB コマンド ウィンドウでコマンドを貼り付けます。
モデル内で 1 度だけ呼び出される C/C++ 関数
この例では、モデル内で C Caller (Simulink) ブロックから 1 度だけ呼び出される関数を使用します。解析では C Caller ブロックへの入力を使用して関数をチェックします。
カスタム コードの解析を実行するためのモデルを開く
Polyspace でカスタム コードを解析するためのモデル mSlccBusDemo
を開きます。このモデルには、ファイル hCounterBus.c
で定義されている (ファイル hCounterBus.h
で宣言されている) 関数 counterbusFcn
を呼び出す C Caller ブロックが含まれています。このモデルでは、MAT ファイル dLctData.mat
に保存されている変数を使用します。この変数は、コールバックを使用してモデルに読み込まれます。
解析の実行
解析オプションを構成し、Polyspace を実行します。
[アプリ] タブで [Polyspace コード検証] を選択して、[Polyspace] タブを開きます。
解析タイプを指定します。
実行する製品 ([Bug Finder] または [Code Prover]) を選択します。Code Prover 解析ではランタイム エラーが検出される一方、Bug Finder 解析ではコーディングの欠陥とコーディング ルール違反が検出されます。
生成されたコードではなくモデル内のカスタム コードで解析を実行しなければならないことを指定します。
[次のコードの解析] フィールドにモデル名が表示されます。そのフィールドの下で、[最上位モデルとして生成されたコード] ではなく [モデルで使用されるカスタム コード] を選択します。
[解析の実行] を選択します。
MATLAB コマンド ウィンドウで解析の進行状況を確認します。解析後は、[Polyspace] タブで [解析結果] を選択します。結果は Polyspace ユーザー インターフェイスで開きます。
次のように MATLAB から同じ解析を実行することもできます。このスクリプトには、モデルとモデルで使用されている変数を含む .mat
ファイルを読み込むためのコマンドが含まれています。
openExample('polyspace_code_prover/OpenModelForRunningAnalysisOnCustomCodeExample'); load_system('mSlccBusDemo'); load('dLctData.mat'); mlopts = pslinkoptions('mSlccBusDemo'); mlopts.VerificationMode = 'CodeProver'; pslinkrun('-slcc','mSlccBusDemo',mlopts);
問題の修正
解析結果は、Polyspace ユーザー インターフェイスの [結果のリスト] ペインに表示されます。各結果を選択すると、[結果の詳細] ペインに詳細が表示され、[ソース] ペインに対応するソース コードが表示されます。
このチュートリアルでは、Code Prover 解析で検出された問題を調べて修正する方法を示します。Bug Finder で検出された問題にも、同じ手順を適用できます。
Code Prover 解析を実行する場合、結果にはオレンジの [オーバーフロー] チェックが含まれます。
このチェックは、オーバーフローする可能性のある関数 counterbusFcn
内の加算演算を強調表示します。
limit = u1->inputsignal.input + u2;
counterbusFcn
への入力によるもので、その入力は次の C Caller ブロックへの入力によるものです。
バス
COUNTERBUS
。信号input
、upper_saturation_limit
、lower_saturation_limit
を結合します。信号input
に制限はありません。Delay ブロックを介した C Caller ブロック自身からのフィードバック。
信号 input
はいくつかの方法で制約できます。たとえば、input
を含む SIGNALBUS
という名前の Simulink.Bus
オブジェクトを制約できます。
Simulink ツールストリップの [モデル化] タブで、[設計] ギャラリーの [型エディター] をクリックします。外部データ ソースまたはバスを展開するには、その名前の横にある矢印をクリックします。
ベース ワークスペースには
SIGNALBUS
という名前のSimulink.Bus
オブジェクトが含まれています。型エディターで [ビュー] を
[値]
に設定し、SIGNALBUS
を展開します。SIGNALBUS
のinput
要素の最小値と最大値を指定します。バス オブジェクトを MAT ファイルに保存します。ファイル
dLctData.mat
を上書きすることも、ファイルを作成することもできます。
いくつかの方法により、C Caller ブロックからのフィードバックを制約することもできます。たとえば、フィードバック信号は次のように飽和できます。
フィードバック信号が C Caller ブロックに入力される直前に Saturation ブロックを追加します。
[信号属性] タブで、Saturation ブロック出力の最小値と最大値を指定します。
Saturation ブロックの [メイン] タブで上限および下限を指定するだけでは Polyspace 解析の信号を制限するには十分ではないことに注意してください。解析では [信号属性] タブで指定された設計範囲を使用します。
解析を再実行します。新しい結果のセットの [オーバーフロー] チェックはグリーンです。
モデルで複数回呼び出される C/C++ 関数
この例では、モデルの複数の C Caller ブロックから呼び出される関数を使用します。この関数は、その 2 つの引数の積を単純に返します。
この例では Code Prover 解析を実行し、Code Prover の結果から始まる関数呼び出しコンテキストを決定する方法を示します。通常、Bug Finder 解析では、異なる呼び出しコンテキストを区別する必要はありません。
すべてのカスタム コード解析のためのモデルを開く
Polyspace 解析を実行するためのモデル multiCCallerBlocks
を開きます。
openExample('polyspace_bf/OpenModelForAnalyzingAllCustomCodeExample'); open_system('multiCCallerBlocks');
モデルの検査
モデルには同じ関数 times_n
を呼び出す 2 つの C Caller ブロックが含まれています。1つの C Caller ブロックへの入力は、制限されていない入力をもつ 2 つの Inport ブロックに由来するものです。もう 1 つの C Caller ブロックへの入力は、Constant ブロックおよび Inport ブロック (Saturation ブロックにより制限された入力をもつ) に由来するものです。
制限された入力をもつ C Caller ブロックの設計範囲を確認するには、次のようにします。
Constant ブロックまたは Saturation ブロックをダブルクリックします。
[信号属性] タブで設計範囲に着目します。
たとえば、Constant ブロックに 3 に設定された定数があるにもかかわらず、検証の設計範囲は 2.5 から 3.5 です。
Saturation ブロックの設計範囲は [-1,1] です。
解析の実行と結果のレビュー
前述の例のように解析を実行し、結果を開きます。
[結果のリスト] ペインにはオレンジの [オーバーフロー] チェックが表示されます。関数 times_n
内の積がオーバーフローします。
#include "file.h"
double times_n(double x, double n) {
return x * n;
}
times_n
が 2 つのコンテキストから呼び出されるため、オレンジ色が両方のコンテキストを結合し、可能性のある 2 つの状況を示しています。
両方の呼び出しコンテキストでオーバーフローが発生する。
1 つのコンテキストではオーバーフローが発生しないことが実証されており (グリーンのチェック)、もう 1 つのコンテキストでは発生する可能性がある (オレンジのチェック)。
どちらのコンテキストがオーバーフローにつながるかを判別するには次のようにします。
times_n
の呼び出し元を確認します。オレンジの [オーバーフロー] チェックを選択します。[結果の詳細] ペインで
をクリックします。[呼び出し階層] ペインに
times_n
の呼び出し元が表示されます。[呼び出し階層] ペインに、呼び出し元として 2 つのラッパー関数が表示されます。それぞれのラッパー関数はモデル内の C Caller ブロックを表しています。
ラッパー関数の 1 つを選択し、
customcode_wrappers.c
のソース コードを開きます。[ソース] ペインでラッパー関数のコードを検査します。どの入力がオーバーフローにつながるかを判別するには、下線の付いた入力に対してツールヒントを使用します。
たとえば、制限のある入力をもつ C Caller ブロックのラッパー関数は、次のコードのようになります。
変数のツールヒントを使用して、変数の範囲を特定します。たとえば、変数/* Go to model '<Root>/C Caller1' */ /* Variables corresponding to inputs for block C Caller1 */ real64_T _pslink_C_Caller1_In1; real64_T _pslink_C_Caller1_In2; /* Variables corresponding to outputs for block C Caller1 */ real64_T _pslink_C_Caller1_Out1; /* Wrapper functions for code in block C Caller1 */ void _pslink_step_C_Caller1(void) { /* See tooltips on function inputs for input ranges */ _pslink_C_Caller1_Out1 = times_n(_pslink_C_Caller1_In1, _pslink_C_Caller1_In2); }
_pslink_C_Caller1_In1
のツールヒントは、これが [2.5, 3.5] の範囲にあることを示しており、_pslink_C_Caller1_In2
のツールヒントは、これが [-1,1] の範囲にあることを示しています。そのため、この 2 つの入力の積はオーバーフローを起こすことがありません。オーバーフローは別の呼び出しコンテキストに由来するはずです。他の呼び出しへの入力のツールヒントを表示して、変数が無制限であることを確認できます。ラッパー関数に対応する C Caller ブロックを見つけるには、[ソース] ペインで、(
Go to model
で始まる行の) ラッパー関数の上にあるブルーのブロック名のリンクをクリックします。モデル内で C Caller ブロックが強調表示されます。
状況依存性の有効化と解析の再実行
この例では、関数は単純であるため、どの呼び出しコンテキストがオーバーフローにつながるかということは、関数の入力自体から判別が可能です。より複雑な関数では、解析を設定して、2 つのコンテキストからの結果を別個に表示できます。
呼び出しコンテキストを区別するにはより深い解析が必要となるため、解析はより時間がかかる可能性があります。そのため、特定の関数に対してのみ、かつ、呼び出しコンテキストを検査では区別できない場合にのみ、状況依存性を有効化します。
この例では、関数 times_n
に対して状況依存性を有効化するには次のようにします。
モデルの [Polyspace] タブで、[設定] 、 [プロジェクトの設定] を選択します。
または Polyspace ユーザー インターフェイスで [プロジェクト ブラウザー] を選択します。解析用に作成されたプロジェクトの設定を開きます。
[Code Prover 検証] 、 [精度] ノードでオプション [状況依存性] に
[カスタム]
を選択します。[手続き] フィールドで、をクリックして
times_n
と入力します。状況依存性 (-context-sensitivity)
も参照してください。
モデルから解析を再実行し、結果を再度開きます。オレンジの [オーバーフロー] チェックを選択します。
[結果の詳細] ペインに呼び出しコンテキストが別個に表示されます。オーバーフローは制限されていない入力をもつ呼び出し (オレンジのテキストの行) に対してのみ発生し、他の呼び出し (グリーンのテキストの行) では発生しないことがわかります。
オレンジのテキストの行をクリックして、オレンジ チェックにつながっているラッパー関数に直接移動します。ラッパー関数から制限されていない入力をもつ C Caller ブロックに移動できます。