Сгенерируйте входящий код из подсистем

Можно уменьшить количество кода, которое генератор кода производит для идентичных атомарных подсистем путем конфигурирования подсистем как переиспользуемых функций, которые передают данные как аргументы (для примера, rtB_* для блочных входных и выходных параметров, rtDW_* для непрерывных состояний и rtP_* для параметров). По умолчанию генератор кода создает код подсистемы, который взаимодействует с другим кодом, делясь доступом к глобальным данным структурам, которые находятся в общей памяти. Передавая данные в качестве аргументов, код может быть входным. Каждый образец кода поддерживает свои уникальные данные.

Чтобы сконфигурировать подсистемы для переиспользуемости и переприсоединения, сконфигурируйте маску и параметры блоков идентичных подсистем так же. Генератор кода выполняет контрольную сумму, чтобы определить, идентичны ли подсистемы и является ли код повторно используемым. Если код переиспользуется, генератор кода создает один образец переиспользуемого, повторно входящего кода функции.

Чтобы сконфигурировать параметры блоков подсистемы:

  1. Если подсистема виртуальна, выберите параметры блоков Threat as atomic unit, чтобы включить параметры упаковки функций.

  2. Установите параметры блоков Function packaging в Reusable function. Генератор кода производит отдельную функцию с аргументами для каждой подсистемы. Выбор Reusable function также включает дополнительные параметры, которые можно использовать для управления именами функции и файла, которые генератор кода производит для кода подсистемы.

  3. Выберите значение для параметров блоков имя функции options. Чтобы сгенерировать повторно используемый, повторно входящий код, задайте ту же настройку для идентичных подсистем.

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

    • Чтобы использовать имя подсистемы или, для библиотечного блока, имя библиотечного блока, выберите Use subsystem name.

    • Чтобы отобразить блочный параметр Function name и ввести уникальное, допустимое имя функции C/C + +, выберите User specified.

    Если в иерархии модели-ссылки существуют несколько образцы идентичной подсистемы, выберите Auto.

    Если вы используете Embedded Coder®можно использовать элементы управления форматом идентификаторов. См. «Управление форматом идентификатора».

  4. Установите опции имени файла. Чтобы сгенерировать повторно используемый, повторно входящий код, задайте ту же настройку для идентичных подсистем.

    • Чтобы позволить генератору кода определить имя файла выбрать Auto.

    • Чтобы использовать имя подсистемы или, для библиотечного блока, имя библиотечного блока, выберите Use subsystem name.

    • Чтобы использовать имя функции, заданное параметрами блоков Function name options выберите Use function name.

    • Чтобы отобразить параметры блоков Имя файла (без расширения) и введите имя файла, исключая расширение (для примера, .c или .cpp) выберите User specified.

    Другие факторы:

    • Если в иерархии модели-ссылки существуют несколько образцы идентичной подсистемы, выберите Auto.

    • Если генератор кода не генерирует отдельный файл для подсистемы, код функции помещается в файл, сгенерированный из родительской системы подсистемы. Если родительский элемент является самой моделью, генератор кода помещает код функции в model.c или model.cpp.

    • Если ваш сгенерированный код находится под системой контроля версий, задайте значение, отличное от Auto. Эта спецификация препятствует изменению имени сгенерированного файла при изменении и перестройке модели.

    • Если вы выбираете Use subsystem nameгенератор кода управляет именем файла подсистемы, если модель содержит блоки Model, или если для модели генерируется цель модели-ссылки. В этих ситуациях генератор кода использует имя файла modelsubsystem.c.

Если подсистема A имеет маскирующий параметр b и K и подсистема B имеет маскирующие параметры c и K, повторное использование кода невозможно. Генератор кода производит отдельные функции для подсистем A и B. Если установить параметры блоков для подсистем A и B по-другому, повторное использование кода невозможно.

Повторное использование функции в сгенерированном коде

В этом примере показано, как сконфигурировать атомарную подсистему для генерации повторно используемого кода. Чтобы указать, что код, сгенерированный для подсистемы, выполняется как атомарный модуль, в диалоговом окне Параметры Блоков выберите параметр Treat as atomic unit. Этот параметр включает параметр Function Packaging на вкладке Генерация Кода. Параметр Function Packaging имеет следующие четыре настройки:

  • Inline: Введите код подсистемы

  • Nonreusable function: Функция с ввод-вывод, переданная как глобальные данные

  • Reusable function: Функция с вводом-выводом передается как аргументы функции

  • Auto: Позвольте Simulink Coder оптимизировать на основе контекста

The Reusable function и Auto настройки позволяют генератору кода повторно использовать код подсистемы. The Reusable function и Nonreusable function включить параметры Function name, Function name и File name.

Если у вас есть лицензия Embedded Coder, можно настроить неиспользуемую подсистему, чтобы принимать аргументы.

Пример модели

The rtwdemo_ssreuse модель содержит две одинаковые подсистемы, SS1 и SS2. Для этих подсистем параметр Function packaging устанавливается в Reusable function, и параметр имя функции myfun. Подсистемы являются параметризованными маскированными подсистемами. Чтобы увидеть содержимое маскированных подсистем, щелкните правой кнопкой мыши блоки подсистемы и выберите «Маска» > «Смотреть под маской».

model = 'rtwdemo_ssreuse';
open_system(model);

Сгенерируйте и смотрите код

Создайте временную папку для процесса сборки и проверки. Откройте приложение Simulink Coder или Embedded Coder. Затем сгенерируйте и проверьте код.

currentDir=pwd;
[~,cgDir]=rtwdemodir();
slbuild(model)
### Starting build procedure for: rtwdemo_ssreuse
### Successful completion of build procedure for: rtwdemo_ssreuse

Build Summary

Top model targets built:

Model            Action                       Rebuild Reason                                    
================================================================================================
rtwdemo_ssreuse  Code generated and compiled  Code generation information file does not exist.  

1 of 1 models built (0 models already up to date)
Build duration: 0h 0m 7.9372s
cfile=fullfile(cgDir, 'rtwdemo_ssreuse_grt_rtw', 'rtwdemo_ssreuse.c');
rtwdemodbtype(cfile, '/* Model step', '/* Model initialize', 1, 0);
/* Model step function */
void rtwdemo_ssreuse_step(void)
{
  /* Outputs for Atomic SubSystem: '<Root>/SS1' */

  /* Inport: '<Root>/In1' incorporates:
   *  Inport: '<Root>/In2'
   */
  myfun(rtwdemo_ssreuse_U.In1, rtwdemo_ssreuse_U.In2, rtwdemo_ssreuse_P.T1Data,
        rtwdemo_ssreuse_P.T1Break, &rtwdemo_ssreuse_B.SS1);

  /* End of Outputs for SubSystem: '<Root>/SS1' */

  /* Outport: '<Root>/Out1' */
  rtwdemo_ssreuse_Y.Out1 = rtwdemo_ssreuse_B.SS1.LookupTable;

  /* Outputs for Atomic SubSystem: '<Root>/SS2' */

  /* Inport: '<Root>/In1' incorporates:
   *  Inport: '<Root>/In2'
   */
  myfun(rtwdemo_ssreuse_U.In1, rtwdemo_ssreuse_U.In2, rtwdemo_ssreuse_P.T2Data,
        rtwdemo_ssreuse_P.T2Break, &rtwdemo_ssreuse_B.SS2);

  /* End of Outputs for SubSystem: '<Root>/SS2' */

  /* Outport: '<Root>/Out2' */
  rtwdemo_ssreuse_Y.Out2 = rtwdemo_ssreuse_B.SS2.LookupTable;
}

В функции шага модели существует два вызова переиспользуемой функции myfun. Параметры маски, T1Break, T1Data, T2Break, и T2Data, являются аргументами функции.

Измените параметр Function Packaging на Inline.

set_param('rtwdemo_ssreuse/SS1','RTWSystemCode','Inline')
set_param('rtwdemo_ssreuse/SS2','RTWSystemCode','Inline')

Сгенерируйте и проверьте код.

slbuild(model)
### Starting build procedure for: rtwdemo_ssreuse
### Successful completion of build procedure for: rtwdemo_ssreuse

Build Summary

Top model targets built:

Model            Action                       Rebuild Reason                   
===============================================================================
rtwdemo_ssreuse  Code generated and compiled  Generated code was out of date.  

1 of 1 models built (0 models already up to date)
Build duration: 0h 0m 6.3775s
cfile=fullfile(cgDir, 'rtwdemo_ssreuse_grt_rtw', 'rtwdemo_ssreuse.c');
rtwdemodbtype(cfile, '/* Model step', '/* Model initialize', 1, 0);
/* Model step function */
void rtwdemo_ssreuse_step(void)
{
  real_T Out1_tmp;

  /* Outputs for Atomic SubSystem: '<Root>/SS2' */
  /* Outputs for Atomic SubSystem: '<Root>/SS1' */
  /* Sum: '<S1>/Sum' incorporates:
   *  Inport: '<Root>/In1'
   *  Inport: '<Root>/In2'
   *  Sum: '<S2>/Sum'
   */
  Out1_tmp = rtwdemo_ssreuse_U.In1 + rtwdemo_ssreuse_U.In2;

  /* End of Outputs for SubSystem: '<Root>/SS2' */

  /* Outport: '<Root>/Out1' incorporates:
   *  Lookup_n-D: '<S1>/Lookup Table'
   *  Sum: '<S1>/Sum'
   */
  rtwdemo_ssreuse_Y.Out1 = look1_binlx(Out1_tmp, rtwdemo_ssreuse_P.T1Break,
    rtwdemo_ssreuse_P.T1Data, 10U);

  /* End of Outputs for SubSystem: '<Root>/SS1' */

  /* Outputs for Atomic SubSystem: '<Root>/SS2' */
  /* Outport: '<Root>/Out2' incorporates:
   *  Lookup_n-D: '<S2>/Lookup Table'
   */
  rtwdemo_ssreuse_Y.Out2 = look1_binlx(Out1_tmp, rtwdemo_ssreuse_P.T2Break,
    rtwdemo_ssreuse_P.T2Data, 10U);

  /* End of Outputs for SubSystem: '<Root>/SS2' */
}

В функции шага модели вставляется код подсистемы.

Измените параметр Function Packaging на Nonreusable function. Для SS2 , измените параметр Имени функции на myfun2.

set_param('rtwdemo_ssreuse/SS1','RTWSystemCode','Nonreusable function')
set_param('rtwdemo_ssreuse/SS2','RTWSystemCode','Nonreusable function')
set_param('rtwdemo_ssreuse/SS2','RTWFcnName','myfun2')

Сгенерируйте и проверьте код.

slbuild(model)
### Starting build procedure for: rtwdemo_ssreuse
### Successful completion of build procedure for: rtwdemo_ssreuse

Build Summary

Top model targets built:

Model            Action                       Rebuild Reason                   
===============================================================================
rtwdemo_ssreuse  Code generated and compiled  Generated code was out of date.  

1 of 1 models built (0 models already up to date)
Build duration: 0h 0m 6.3979s
cfile=fullfile(cgDir, 'rtwdemo_ssreuse_grt_rtw', 'rtwdemo_ssreuse.c');
rtwdemodbtype(cfile, '/* Model step', '/* Model initialize', 1, 0);
/* Model step function */
void rtwdemo_ssreuse_step(void)
{
  /* Outputs for Atomic SubSystem: '<Root>/SS1' */
  myfun();

  /* End of Outputs for SubSystem: '<Root>/SS1' */

  /* Outputs for Atomic SubSystem: '<Root>/SS2' */
  myfun2();

  /* End of Outputs for SubSystem: '<Root>/SS2' */
}

Функция шага модели содержит вызовы функций myfun и myfun2. Эти функции имеют пустой интерфейс.

Измените параметр Function Packaging на Auto.

set_param('rtwdemo_ssreuse/SS1','RTWSystemCode','Auto')
set_param('rtwdemo_ssreuse/SS2','RTWSystemCode','Auto')

Для auto Simulink Coder выбирает оптимальный формат. Для этой модели оптимальным форматом является переиспользуемая функция.

Закройте модель и очистите.

bdclose(model)
rtwdemoclean;
cd(currentDir)

Ограничения

  • Генератор кода использует контрольную сумму, чтобы определить, являются ли подсистемы идентичными и многоразовыми. Код подсистемы не используется повторно, если:

    • В блоках и объектах данных для задания размерностей используются символы.

    • Порт имеет различные шаги расчета, типы данных, сложность, состояние системы координат или размерности по подсистемам.

    • Выход подсистемы помечается как глобальный сигнал.

    • Подсистемы содержат одинаковые блоки с различными именами или настройками параметров.

    • Выход подсистемы соединяется с блоком Merge, а выход блока Merge сконфигурирован с пользовательским классом памяти, который реализован в Код С как не аддрессируемая память (для примера, BitField).

    • Вход подсистемы является нескалярным и сконфигурирован с пользовательским классом памяти, который реализован в коде С как не аддрессируемая память.

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

    • Подсистема вызова функций использует параметры маски, когда вы устанавливаете параметр конфигурации модели Поведение параметра по умолчанию равным Tunable. Чтобы повторно использовать маскированную подсистему вызова функций, поместите ее в новую атомарную подсистему без маски. Затем переместите блок Trigger из маскированной подсистемы в атомарную подсистему.

    • Блок в подсистеме использует partially tunable expression. Некоторые частично настраиваемые выражения отключают повторное использование кода.

      Частично настраиваемые выражения являются выражениями, которые содержат одну или несколько настраиваемых переменных и выражение, которое не настраивается. Например, предположим, что вы создаете настраиваемую переменную K со значением 15.23 и настраиваемой переменной P со значением [5;7;9]. Выражение K+P' является частично настраиваемым выражением, поскольку выражение P' не настраивается. Для получения дополнительной информации о настраиваемых ограничениях выражения смотрите Настраиваемые ограничения выражения.

  • Для подсистем, которые содержат блоки s-function, которые являются переиспользуемыми, блоки должны отвечать требованиям, перечисленным в S-Функциях для повторного использования кода.

  • Если вы выбираете Reusable function, и генератор кода определяет, что вы не можете повторно использовать код для подсистемы, он генерирует отдельную функцию, которая не используется повторно. Отчет генерации кода может показать, что отдельная функция переиспользуется, даже если ею пользуется только одна подсистема. Если вы предпочитаете, чтобы код встроенной подсистемы генератора кода в таких случаях (а не развертывался как функции), установите Function packaging на Auto.

  • Если переиспользуемая подсистема использует общее локальное хранилище данных и вы конфигурируете отображение по умолчанию для элементов данных моделей, оставьте отображение классов памяти по умолчанию для категории Shared local data stores установленным на Default.

  • Использование этих блоков в подсистеме может предотвратить повторное использование кода подсистемы:

    • Блоки scope (с включенным логгированием данных)

    • Блоки S-Function, которые не удовлетворяют определенным критериям (см. S-Functions for Повторное Использование Кода)

    • Блоки To File (с включенным логгированием данных)

    • В блоки Рабочей области (с включенным логгированием данных)

  • Для переиспользуемых подсистем библиотеки (подсистемы, общие для образцов модели) генератор кода использует контрольную сумму, чтобы определить, являются ли подсистемы идентичными. Генератор кода помещает переиспользуемый библиотечный подсистемный код в общую папку утилит, и переиспользуемый код не зависит от сгенерированного кода модели верхней части или образца модели. Например, переиспользуемый код подсистемы библиотеки не включает model.h или model_types.h.

    Переиспользуемый код, который генератор кода помещает в общую папку утилит и зависит от кода модели, не компилируется. Если генератор кода определяет, что повторно используемый библиотечный подсистемный код зависит от кода модели, повторно используемый подсистемный код не помещается в общую папку утилит. Генератор кода производит код, который зависит от кода модели, когда переиспользуемая библиотечная подсистема:

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

    • Содержит один или несколько блоков Model.

    • Содержит подсистему, которая не является встроенной или переиспользуемой подсистемой библиотеки.

    • Содержит сигнал или параметр с классом памяти, который помещает объявление данных в файл под model_ert_rtw (Например, ExportedGlobal класс памяти помещает данные в model.c)

    • Содержит определяемый пользователем класс памяти, такой как Enumeration, Simulink .Signal, Simulink. Параметр и так далее, где Data Scope не задано Exported. Генератор кода может поместить определение типа в model_types.h.

    • Является вариантной подсистемой, которая генерирует предварительные условия процессора. Генератор кода помещает директивы препроцессора, которые определяют объекты варианта в model_types.h

  • Вы не можете повторно использовать подсистему, если в модели есть несколько образцы одной и той же подсистемы, и одна подсистема питается от блока Constant, но другая подсистема не работает. Чтобы обойти это ограничение, вставьте блок Signal Conversion перед подсистемами.

  • Две переиспользуемые подсистемы, которые имеют различные контрольные суммы, не могут совместно использовать одну и ту же функцию в сгенерированном коде. Когда вы задаете одно и то же имя функции для обеих подсистем в Block Parameters (Subsystem) > Code Generation > Function name:

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

    • Если подсистемы не связаны с библиотекой, генератор кода выдает ошибку.

Предыдущие ограничения также применяются к генерации кода на основе библиотек. Для получения дополнительной информации см. «Библиотечная Генерация кода для переиспользуемых библиотечных подсистем».

Похожие темы