サブシステム コードが再利用されない理由
サブシステムからの再呼び出し可能なコードの生成で説明されている制限のために、コード ジェネレーターは生成されたコードを期待どおりに再利用しない可能性があります。サブシステム用に生成されたコードが再利用されない理由を判断するには、以下を実行します。
コード生成レポートのサブシステム セクションを確認する。
サブシステムのチェックサム データを比較する。
HTML コード生成レポートのサブシステム セクションの確認
サブシステムを再利用可能と指定したにもかかわらず、コード ジェネレーターがサブシステムのコードを再利用可能なコードとして生成していない場合は、コード生成レポートのサブシステム セクションを調べます (コード生成レポートの生成を参照)。サブシステム セクションには次の情報が表示されます。
非バーチャルなサブシステムが生成コードに変換されるプロセスをまとめた表。
サブシステムが再利用可能なコードとして生成されなかった理由を説明する診断情報。
サブシステム セクションは、モデルのインライン化されていない各サブシステムと生成されたコードの関数や再利用可能な関数を対応付けます。例については、サブシステム コードを別々の関数およびファイルとして生成でモデル SubsystemAtomic
を参照してください。
サブシステムのチェックサム データの比較
サブシステムのチェックサム データを比較することによって、サブシステム コードが再利用されない理由を判断できます。コード ジェネレーターは、制限に説明されているように、システムのチェックサムを比較することでサブシステムが同一であるかどうかを判断します。サブシステムは複数の参照モデル間で再利用されるため、この手順ではすべての相違点にフラグを設定できない可能性があります。
たとえば、モデル GeneratedCodeFunctionReuse
があるとします。SS1
と SS2
は同じサブシステムのインスタンスです。どちらのインスタンスも、サブシステム ブロック パラメーター [関数のパッケージ化] は [再利用可能な関数]
に設定されています。
メソッド Simulink.SubSystem.getChecksum
を使用して、サブシステムのチェックサムを取得します。結果を確認して、コードが再利用されない理由を判断します。
モデル
GeneratedCodeFunctionReuse
を開きます。openExample('GeneratedCodeFunctionReuse')
サブシステム
SS1
およびSS2
をgcb
に関連付けます。サブシステムごとに、モデル ウィンドウでサブシステムを選択します。サブシステムを選択している間に、コマンド ウィンドウで次のように入力します。SS1 = gcb;
SS2 = gcb;
メソッド
Simulink.SubSystem.getChecksum
を使用して、各サブシステムのチェックサムを取得します。このメソッドは次の 2 つの出力値を返します。チェックサムの値、およびチェックサムを計算するために使用した入力の詳細。[chksum1, chksum1_details] = ... Simulink.SubSystem.getChecksum(SS1); [chksum2, chksum2_details] = ... Simulink.SubSystem.getChecksum(SS2);
2 つのチェックサムの値を比較します。サブシステムのコンフィギュレーションでは、両方の値は等しいはずです。
isequal(chksum1, chksum2) ans = 1
Simulink.SubSystem.getChecksum
を使用して 2 つのサブシステムのチェックサムが異なる理由を判断するには、SS1 の出力端子のデータ型モードを SS2 のものと異なるように変更します。SS1
のマスクの下を参照します。サブシステムを右クリックします。コンテキスト メニューで、[マスク] 、 [マスク内を表示] を選択します。サブシステムのブロック線図で、Lookup Table ブロックをダブルクリックし、[Subsystem パラメーター] ダイアログ ボックスを開きます。
[データ型] をクリックします。
ブロック パラメーター [整数オーバーフローで飽和] を選択し、[OK] をクリックします。
SS1
のチェックサムを取得します。2 つのサブシステムのチェックサムを比較します。今回はチェックサムは一致していません。[chksum1, chksum1_details] = ... Simulink.SubSystem.getChecksum(SS1); isequal(chksum1, chksum2) ans = 0
チェックサムが異なっていることを確認したら、その理由を考えましょう。Simulink® エンジンは信号データ型、ブロック パラメーター値、ブロックの接続情報などの情報を使用してチェックサムを計算します。チェックサムが異なる理由を判断するには、チェックサムの値を計算するデータを比較します。この情報は、
Simulink.SubSystem.getChecksum
で返された 2 番目の値から取得できます。これは 4 つのフィールドをもつ構造体配列です。構造体
chksum1_details
を見てください。chksum1_details chksum1_details = ContentsChecksum: [1x1 struct] InterfaceChecksum: [1x1 struct] ContentsChecksumItems: [287x1 struct] InterfaceChecksumItems: [53x1 struct]
ContentsChecksum
とInterfaceChecksum
はサブシステムのチェックサムのコンポーネント チェックサムです。残りの 2 つのフィールドContentsChecksumItems
とInterfaceChecksumItems
はチェックサムの詳細です。サブシステムの内容、インターフェイス、またはその両方に違いがあるかどうか判断します。以下に例を示します。
isequal(chksum1_details.ContentsChecksum.Value,... chksum2_details.ContentsChecksum.Value) ans = 0 isequal(chksum1_details.InterfaceChecksum.Value,... chksum2_details.InterfaceChecksum.Value) ans = 1
この場合は内容に違いがあります。
次のようなスクリプトを作成して違いを確認します。
idxForCDiffs=[]; for idx = 1:length(chksum1_details.ContentsChecksumItems) if (~strcmp(chksum1_details.ContentsChecksumItems(idx).Identifier, ... chksum2_details.ContentsChecksumItems(idx).Identifier)) disp(['Identifiers different for contents item ', num2str(idx)]); idxForCDiffs=[idxForCDiffs, idx]; end if (ischar(chksum1_details.ContentsChecksumItems(idx).Value)) if (~strcmp(chksum1_details.ContentsChecksumItems(idx).Value, ... chksum2_details.ContentsChecksumItems(idx).Value)) disp(['Character vector values different for contents item ', num2str(idx)]); idxForCDiffs=[idxForCDiffs, idx]; end end if (isnumeric(chksum1_details.ContentsChecksumItems(idx).Value)) if (chksum1_details.ContentsChecksumItems(idx).Value ~= ... chksum2_details.ContentsChecksumItems(idx).Value) disp(['Numeric values different for contents item ', num2str(idx)]); idxForCDiffs=[idxForCDiffs, idx]; end end end
スクリプトを実行します。次の例では、スクリプトの名前を
check_details
と仮定しています。check_details Character vector values different for contents item 202
この結果は、インデックス項目 202 でサブシステムの内容に違いがあることを示しています。
返されたインデックス値を使用して、見つかった違いの各々についてハンドル、識別子、値の詳細を取得します。
chksum1_details.ContentsChecksumItems(202) ans = Handle: 'GeneratedCodeFunctionReuse/SS1/Lookup Table' Identifier: 'SaturateOnIntegerOverflow' Value: 'on'
詳細を見ると、サブシステムの再利用に関する問題においては、Lookup Table ブロック パラメーター [整数オーバーフローで飽和] に重点を置いてデバッグすべきであることがわかります。