Определите, почему код подсистемы не используется повторно

Из-за ограничений, описанных в Generate Reentrant Code from Subsystems, генератор кода может не использовать сгенерированный код повторно, как вы ожидаете. Чтобы определить, почему код, сгенерированный для подсистемы, не используется повторно:

  1. Проверьте раздел «Подсистемы» отчета о генерации кода.

  2. Сравнение данных контрольной суммы подсистемы.

Смотрите раздел подсистем отчета генерации кода HTML

Если генератор кода не генерирует код для подсистемы как повторно используемый код, и вы сконфигурировали подсистему как повторно используемую, исследуйте раздел Subsystems отчета генерации кода (см. «Генерация отчета генерации кода»). Раздел «Подсистемы» содержит:

  • Таблица, в которой результирующее описание преобразования невиртуальных подсистем в сгенерированный код.

  • Диагностическая информация, которая описывает, почему подсистемы не были сгенерированы как повторно используемый код.

Раздел Subsystems также сопоставляет неинлинфицированные подсистемы в модели с функциями или повторно используемыми функциями в сгенерированном коде. Для примера откройте и создайте rtwdemo_atomic модель.

Сравнение данных контрольной суммы подсистемы

Можно определить, почему код подсистемы не используется повторно, сравнивая данные контрольной суммы подсистемы. Генератор кода определяет, являются ли подсистемы идентичными, путем сравнения контрольных сумм подсистемы, как отмечено в Ограничениях. Для повторного использования подсистемы между ссылочными моделями эта процедура может не помечать каждое различие.

Рассмотрим модель, rtwdemo_ssreuse. SS1 и SS2 являются образцами одной и той же подсистемы. В оба образцов параметров блоков подсистемы Function packaging установлено на Reusable function.

Используйте метод Simulink.SubSystem.getChecksum для получения контрольной суммы для подсистемы. Проверьте результаты, чтобы определить, почему код не используется повторно.

  1. Откройте модель rtwdemo_ssreuse. Сохраните копию модели в папке, где у вас есть доступ для записи.

  2. Ассоциируйте подсистемы SS1 и SS2 с gcb. Для каждой из подсистем в окне модели выберите подсистему. Пока подсистема выбрана, в Командном окне введите:

    SS1 = gcb;
    SS2 = gcb;
  3. Используйте метод Simulink.SubSystem.getChecksum для получения контрольной суммы для каждой подсистемы. Этот метод возвращает два выхода значения: значение контрольной суммы и детали о входе, используемой для вычисления контрольной суммы.

    [chksum1, chksum1_details] = ...
    Simulink.SubSystem.getChecksum(SS1);
    [chksum2, chksum2_details] = ...
    Simulink.SubSystem.getChecksum(SS2);
  4. Сравните два значения контрольной суммы. Значения должны быть равными на основе строений подсистемы.

    isequal(chksum1, chksum2)
    ans =
         1
  5. Использовать Simulink.SubSystem.getChecksum чтобы определить, почему контрольные суммы двух подсистем различаются, измените режим типа данных выходного порта SS1 так, чтобы он отличался от режима SS2.

    1. Посмотрите под маской SS1. Щелкните подсистему правой кнопкой мыши. В контекстном меню выберите Mask > Look Under Mask.

    2. На схеме подсистемы дважды кликните блок Lookup Table, чтобы открыть диалоговое окно Параметры.

    3. Нажмите Data Types.

    4. Выберите параметры блоков Saturate on integer overflow и нажатие кнопки OK.

  6. Получите контрольную сумму для SS1. Сравните контрольные суммы для двух подсистем. На этот раз контрольные суммы не равны.

    [chksum1, chksum1_details] = ...
    Simulink.SubSystem.getChecksum(SS1);
    isequal(chksum1, chksum2)
    ans =
         0
  7. После того, как вы определите, что контрольные суммы различаются, узнайте, почему. Simulink® Для вычисления контрольных сумм система использует информацию, такую как типы данных сигналов, некоторые значения параметров блоков и информация о связности блоков. Чтобы определить, почему контрольные суммы отличаются, сравните данные, которые вычисляют значения контрольной суммы. Вы можете получить эту информацию из второго значения, возвращенного Simulink.SubSystem.getChecksum, который является массивом структур с четырьмя полями.

    Посмотрите на структуру chksum1_details.

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

    ContentsChecksum и InterfaceChecksum являются контрольными суммами компонентов контрольной суммы подсистемы. Оставшиеся два поля, ContentsChecksumItems и InterfaceChecksumItems, содержат подробные данные контрольной суммы.

  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: 'rtwdemo_ssreuse/SS1/Lookup Table'
        Identifier: 'SaturateOnIntegerOverflow'
             Value: 'on'
    

    Детали идентифицируют Lookup Table параметров блоков Saturate on integer overflow как особое внимание для отладки проблемы повторного использования подсистемы.