Main Content

サブシステム コードが再利用されない理由

サブシステムからの再呼び出し可能なコードの生成で説明されている制限のために、コード ジェネレーターは生成されたコードを期待どおりに再利用しない可能性があります。サブシステム用に生成されたコードが再利用されない理由を判断するには、以下を実行します。

  1. コード生成レポートのサブシステム セクションを確認する。

  2. サブシステムのチェックサム データを比較する。

HTML コード生成レポートのサブシステム セクションの確認

サブシステムを再利用可能と指定したにもかかわらず、コード ジェネレーターがサブシステムのコードを再利用可能なコードとして生成していない場合は、コード生成レポートのサブシステム セクションを調べます (コード生成レポートの生成を参照)。サブシステム セクションには次の情報が表示されます。

  • 非バーチャルなサブシステムが生成コードに変換されるプロセスをまとめた表。

  • サブシステムが再利用可能なコードとして生成されなかった理由を説明する診断情報。

サブシステム セクションは、モデルのインライン化されていない各サブシステムと生成されたコードの関数や再利用可能な関数を対応付けます。例については、サブシステム コードを別々の関数およびファイルとして生成でモデル SubsystemAtomic を参照してください。

サブシステムのチェックサム データの比較

サブシステムのチェックサム データを比較することによって、サブシステム コードが再利用されない理由を判断できます。コード ジェネレーターは、制限に説明されているように、システムのチェックサムを比較することでサブシステムが同一であるかどうかを判断します。サブシステムは複数の参照モデル間で再利用されるため、この手順ではすべての相違点にフラグを設定できない可能性があります。

たとえば、モデル GeneratedCodeFunctionReuse があるとします。SS1SS2 は同じサブシステムのインスタンスです。どちらのインスタンスも、サブシステム ブロック パラメーター [関数のパッケージ化][再利用可能な関数] に設定されています。

メソッド Simulink.SubSystem.getChecksum を使用して、サブシステムのチェックサムを取得します。結果を確認して、コードが再利用されない理由を判断します。

  1. モデル GeneratedCodeFunctionReuse を開きます。

    openExample('GeneratedCodeFunctionReuse')

  2. サブシステム SS1 および SS2gcb に関連付けます。サブシステムごとに、モデル ウィンドウでサブシステムを選択します。サブシステムを選択している間に、コマンド ウィンドウで次のように入力します。

    SS1 = gcb;
    SS2 = gcb;
  3. メソッド Simulink.SubSystem.getChecksum を使用して、各サブシステムのチェックサムを取得します。このメソッドは次の 2 つの出力値を返します。チェックサムの値、およびチェックサムを計算するために使用した入力の詳細。

    [chksum1, chksum1_details] = ...
    Simulink.SubSystem.getChecksum(SS1);
    [chksum2, chksum2_details] = ...
    Simulink.SubSystem.getChecksum(SS2);
  4. 2 つのチェックサムの値を比較します。サブシステムのコンフィギュレーションでは、両方の値は等しいはずです。

    isequal(chksum1, chksum2)
    ans =
         1
  5. Simulink.SubSystem.getChecksum を使用して 2 つのサブシステムのチェックサムが異なる理由を判断するには、SS1 の出力端子のデータ型モードを SS2 のものと異なるように変更します。

    1. SS1 のマスクの下を参照します。サブシステムを右クリックします。コンテキスト メニューで、[マスク][マスク内を表示] を選択します。

    2. サブシステムのブロック線図で、Lookup Table ブロックをダブルクリックし、[Subsystem パラメーター] ダイアログ ボックスを開きます。

    3. [データ型] をクリックします。

    4. ブロック パラメーター [整数オーバーフローで飽和] を選択し、[OK] をクリックします。

  6. SS1 のチェックサムを取得します。2 つのサブシステムのチェックサムを比較します。今回はチェックサムは一致していません。

    [chksum1, chksum1_details] = ...
    Simulink.SubSystem.getChecksum(SS1);
    isequal(chksum1, chksum2)
    ans =
         0
  7. チェックサムが異なっていることを確認したら、その理由を考えましょう。Simulink® エンジンは信号データ型、ブロック パラメーター値、ブロックの接続情報などの情報を使用してチェックサムを計算します。チェックサムが異なる理由を判断するには、チェックサムの値を計算するデータを比較します。この情報は、Simulink.SubSystem.getChecksum で返された 2 番目の値から取得できます。これは 4 つのフィールドをもつ構造体配列です。

    構造体 chksum1_details を見てください。

    chksum1_details
    
    chksum1_details = 
              ContentsChecksum: [1x1 struct]
             InterfaceChecksum: [1x1 struct]
         ContentsChecksumItems: [287x1 struct]
        InterfaceChecksumItems: [53x1 struct]

    ContentsChecksumInterfaceChecksum はサブシステムのチェックサムのコンポーネント チェックサムです。残りの 2 つのフィールド ContentsChecksumItemsInterfaceChecksumItems はチェックサムの詳細です。

  8. サブシステムの内容、インターフェイス、またはその両方に違いがあるかどうか判断します。以下に例を示します。

    isequal(chksum1_details.ContentsChecksum.Value,...
            chksum2_details.ContentsChecksum.Value)
    ans =
         0
    isequal(chksum1_details.InterfaceChecksum.Value,...
            chksum2_details.InterfaceChecksum.Value)
    ans =
         1

    この場合は内容に違いがあります。

  9. 次のようなスクリプトを作成して違いを確認します。

    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
    
  10. スクリプトを実行します。次の例では、スクリプトの名前を check_details と仮定しています。

    check_details
    Character vector values different for contents item 202

    この結果は、インデックス項目 202 でサブシステムの内容に違いがあることを示しています。

  11. 返されたインデックス値を使用して、見つかった違いの各々についてハンドル、識別子、値の詳細を取得します。

    chksum1_details.ContentsChecksumItems(202)
    
    ans = 
    
            Handle: 'GeneratedCodeFunctionReuse/SS1/Lookup Table'
        Identifier: 'SaturateOnIntegerOverflow'
             Value: 'on'
    

    詳細を見ると、サブシステムの再利用に関する問題においては、Lookup Table ブロック パラメーター [整数オーバーフローで飽和] に重点を置いてデバッグすべきであることがわかります。