Сгенерируйте входящий код из функциональных блоков Simulink

Если вы используете Embedded Coder®можно сгенерировать повторно используемый, повторно входящий код путем представления алгоритма как масштабируемого блока Simulink Function. Примеры того, когда сгенерировать повторный код из блоков Simulink Function, - это когда функция разделяет состояние между вызывающими абонентами функции в модели или для клиентских/серверных приложений. Можно сгенерировать код, который сильно модулируется с помощью нескольких образцов общего блока Simulink Function в модели export-function. Генератор кода производит код функции и связывает каждое использование или вызов функции с данными конкретного экземпляра. Возможности функции зависят от того, помещаете ли вы функцию на корневой уровень модели или в подсистему.

Генератор кода производит код входящей функции, когда вы конфигурируете:

Вызовите функцию, представленную масштабированным блоком Simulink Function, с одного уровня выше, на том же уровне или с уровня ниже уровня определения функции. Можно масштабировать функцию в атомарной или невиртуальной подсистеме, но доступность вызова функции ограничена тем же уровнем или ниже иерархии. Имя функции не должно быть уникальным.

Идентифицируйте требования

До и пока вы проектируете свою модель, примите во внимание:

  • Сколько образцов каждой функции требуется?

  • Нужно ли ограничивать сайты вызовов функции моделью, содержащей определение функции?

  • Вам нужна функция для взаимодействия с сигналами в локальном окружении, но сохраните эти сигналы скрытыми от вызывающих?

  • Должны ли функции взаимодействовать непосредственно друг с другом?

  • Должны ли функции подключаться к внешним вводам-выводам?

  • Вам нужно логгировать выход функции?

Создайте модель

Используйте компонент модели в качестве примера rtwdemo_comp чтобы увидеть, как использовать блоки Simulink Function для генерации повторного кода С Используйте пример модели rtwdemo_comp_cpp если вы предпочитаете сгенерировать код С++. Откройте модель и исследуйте иерархию модели.

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

Ссылка на модель, rtwdemo_func_dinteg, состоит из блока Simulink Function, который задает функцию multiinstfunc и подсистемы subsys_calc.

Подсистема состоит из блока Simulink Function. Это использование блока Simulink Function показывает, как можно ограничить возможности функции, которую определяет блок, моделью, которая содержит подсистему. Генератор кода производит код функции для func_calc и связывает каждый вызов функции с данными конкретного экземпляра. Данные включают в себя состояния, такие как данные, хранящиеся в памяти.

Блок Simulink Function, который задает функцию multiinstfunc использует блок Function Caller для вызова функции func_calc. Этот блок Simulink Function также показывает, что он может взаимодействовать с сигналами в локальном окружении блока через блоки Inport и Outport.

На верхнем уровне модели rtwdemo_comp, подсистема вызова функций использует блоки Function Caller, чтобы вызвать два образцов функции multiinstfunc. Генератор кода создает код функции и связывает каждый вызов с данными конкретного экземпляра.

Сконфигурируйте элементы модели и модели

Сконфигурируйте функциональные блоки Simulink

Сконфигурируйте блоки Simulink Function путем установки параметров для блока function Trigger Port. Чтобы генератор кода произвел повторный код из блоков Simulink Function:

  • Сконфигурируйте образцы блоков с таким же именем функции.

  • Установите параметры блоков Function visibility в scoped.

В примере имя функции для Simulink Function блокируется в двух экземплярах модели-ссылки rtwdemo_func_dinteg задается как multiinstfunc.

Сконфигурируйте блоки вызывающего абонента функции

Сконфигурируйте блоки Function Caller. Для каждого из блоков установите параметры блоков Function prototype. Начните набирать прототип. Для примера введите y. Опции прототипа, основанные на определениях функций в модели, появляются в списке выбора. Выберите прототип, который соответствует каждому вызову функции.

В данном примере прототипы сконфигурированы следующим образом:

  • В подсистеме вызова функций прототипы для вызывающих абонентов функции сконфигурированы следующим образом y = Instance1.multiinstfunc(u) и y = Instance2.multiinstfunc(u). Образец n префикс идентифицирует каждый вызов функции уникально и связывает вызов со своим собственным набором данных.

  • Вызывающий абонент функции в функции multiinstfunc сконфигурирован с прототипом y = subsys_calc.func_calc(u). Префикс subsys_calc определяет подсистему, содержащую определение функции.

Для примера спецификации входа и выходных аргументов и шага расчета сохраняют настройки по умолчанию.

Строение подсистемы

Изменения строения не требуются для подсистемы в модели примера. Когда вы включаете блок Simulink Function в подсистему, генератор кода

  • Масштабирует функцию в модель, которая включает подсистему.

  • Обрабатывает подсистему как атомарный модуль.

Сконфигурируйте ссылочную модель

Сконфигурируйте ссылку на модель, которая включает блок Simulink Function:

  • В диалоговом окне Параметров блоков установите Model name параметра на имя файла модели-ссылки. В данном примере имя модели rtwdemo_func_dinteg.slx.

  • Установите Total number of instances allowed per top model параметра конфигурации модели в Multiple.

  • Чтобы сгенерировать интерфейс класса C++ для образца модели, установите параметр конфигурации модели Language равным C++ и Code interface packaging параметров в C++ class.

Опционально можно настроить интерфейсы функции точки входа модели. Можно задать имена функции точки входа. Для функции точки входа выполнения (шага) можно сконфигурировать имя функции и аргументы. Пользовательские интерфейсы функций точки входа могут минимизировать изменения в существующем внешнем коде, который вы интегрируете с сгенерированным кодом. В примере используются функциональные интерфейсы по умолчанию. Смотрите Configure Entry-Point Function Interfaces для блоков Simulink Function и Function Caller (Embedded Coder).

Сконфигурируйте верхнюю часть

Сконфигурируйте верхнюю модель для компонента модели. Если вы хотите, чтобы компонент модели (то есть верхняя модель) был переиспользуемым, установите параметр конфигурации модели Code interface packaging равным Reusable function. Если вы генерируете код С++, можно задать этот параметр C++ class. В любом случае также:

  • Установите Multi-instance code error diagnostic параметра конфигурации модели в Error.

  • Установите Pass root-level I/O as параметра конфигурации модели в Part of model data structure.

Опционально можно настроить интерфейсы функции точки входа модели. Можно задать имена функции точки входа. Для функции точки входа выполнения (шага) можно сконфигурировать имя функции и аргументы. Пользовательские интерфейсы функций точки входа могут минимизировать изменения в существующем внешнем коде, который вы интегрируете с сгенерированным кодом. В примере используются функциональные интерфейсы по умолчанию. Смотрите Configure Entry-Point Function Interfaces для блоков Simulink Function и Function Caller (Embedded Coder).

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

Сгенерируйте код С для модели.

  • Код функции для блока Simulink Function с мультиобразцами

    Когда вы помещаете масштабированный блок Simulink Function в модель-ссылку, которую вы используете несколько раз в другой модели, генератор кода помещает код функции в model.c файл для ссылочной модели. В данном примере генератор кода помещает код функции для multiinstfunc в slprj/ert/rtwdemo_func_dinteg/rtwdemo_func_dinteg.c.

    real_T rtwdemo_func_dinteg_multiinstfunc(RT_MODEL_rtwdemo_func_dinteg_T * const
      rtwdemo_func_dinteg_M, const real_T rtu_u)
    {
      real_T rtb_TmpLatchAtInOutport1;
      real_T rtb_TmpLatchAtIn2Outport1;
      real_T rty_y_0;
    
      rtb_TmpLatchAtInOutport1 =
        *rtwdemo_func_dinteg_M->rtwdemo_func_dintegrtextInport.rtu_In1;
    
      rtb_TmpLatchAtIn2Outport1 =
        *rtwdemo_func_dinteg_M->rtwdemo_func_dintegrtextInport.rtu_In2;
    
      *rtwdemo_func_dinteg_M->rtwdemo_func_dintegrtextOutport.rty_Out2 = 2.0 *
        rtb_TmpLatchAtInOutport1;
      
      rtwdemo_func_dinteg_func_calc(rtwdemo_func_dinteg_M, rtb_TmpLatchAtIn2Outport1,
        rtwdemo_func_dinteg_M->rtwdemo_func_dintegrtextOutport.rty_Out1);
    
      rty_y_0 = rtwdemo_func_dinteg_M->dwork.DiscreteIntegrator_DSTATE;
    
      rtwdemo_func_dinteg_M->dwork.DiscreteIntegrator_DSTATE += 0.1 * rtu_u;
      return rty_y_0;
    }
    
  • Код функции для блока Simulink Function, заданный в подсистеме

    Генератор кода помещает код функции для блока Simulink Function, который вы задаете в подсистеме в model.c файл для модели, которая содержит подсистему. В данном примере генератор кода помещает код функции для func_calc в slprj/ert/rtwdemo_func_dinteg/rtwdemo_func_dinteg.c.

    void rtwdemo_func_dinteg_func_calc(RT_MODEL_rtwdemo_func_dinteg_T * const
      rtwdemo_func_dinteg_M, real_T rtu_u, real_T *rty_y)
    {
      rtwdemo_func_dinteg_M->dwork.calcMem =
        rtwdemo_func_dinteg_M->dwork.UnitDelay_DSTATE;
    
      *rty_y = rtwdemo_func_dinteg_M->dwork.UnitDelay_DSTATE;
    
      rtwdemo_func_dinteg_M->dwork.UnitDelay_DSTATE = rtu_u * 0.07;
    }
    
  • Структура, которая хранит данные мультиобразцов для переиспользуемых функций

    Генератор кода использует структуру, подобную модели реального времени (RT_MODEL) структура данных для хранения данных мультиобразцов, сопоставленных с переиспользуемой функцией. Генератор кода определяет структуру в slprj/ert/rtwdemo_func_dinteg/rtwdemo_func_dinteg.h.

    typedef struct rtwdemo_func_dinteg_tag_RTM RT_MODEL_rtwdemo_func_dinteg_T;
    
  • Код инициализации для модели с мультиобразцами

    Для каждого образца ссылочной модели, который включает в себя один и тот же масштабированный блок Simulink Function, генератор кода производит инициализацию и код функции запуска. Одна копия кода инициализации определяется как slprj/ert/rtwdemo_func_dinteg/rtwdemo_func_dinteg.c.

    void rtwdemo_func_dinteg_Start(RT_MODEL_rtwdemo_func_dinteg_T *const
      rtwdemo_func_dinteg_M, const real_T *rtu_In1, const real_T *rtu_In2, real_T
      *rty_Out2, real_T *rty_Out1)
    {
      rtwdemo_func_dinteg_M->rtwdemo_func_dintegrtextInport.rtu_In1 = rtu_In1;
      rtwdemo_func_dinteg_M->rtwdemo_func_dintegrtextInport.rtu_In2 = rtu_In2;
      rtwdemo_func_dinteg_M->rtwdemo_func_dintegrtextOutport.rty_Out2 = rty_Out2;
      rtwdemo_func_dinteg_M->rtwdemo_func_dintegrtextOutport.rty_Out1 = rty_Out1;
    }
    
    void rtwdemo_func_dinteg_initialize(const char_T **rt_errorStatus,
      RT_MODEL_rtwdemo_func_dinteg_T *const rtwdemo_func_dinteg_M)
    {
      {
        rtmSetErrorStatusPointer(rtwdemo_func_dinteg_M, rt_errorStatus);
      }
    }
    

    Код инициализации вызывается для каждого образца ссылочной модели, который содержит один и тот же блок Simulink Function. Этот код находится в файле rtwdemo_comp.c в папке сборки.

    .
    .
    .
    rtwdemo_func_dinteg_initialize(rtmGetErrorStatusPointer(rtwdemo_comp_M),
      (&(rtwdemo_comp_M->Instance1)));
      
    rtwdemo_func_dinteg_initialize(rtmGetErrorStatusPointer(rtwdemo_comp_M),
      (&(rtwdemo_comp_M->Instance2)));
    
    rtwdemo_func_dinteg_Start((&(rtwdemo_comp_M->Instance1)), &rtU->In2, &rtU->In3,
      &rtY->Out2, &rtY->Out3);
      
    rtwdemo_func_dinteg_Start((&(rtwdemo_comp_M->Instance2)), &rtU->In4, &rtU->In5,
      &rtY->Out4, &rtY->Out5);
    }
    
  • Объявления функции точки входа верхней модели

    Файл заголовка модели rtwdemo_comp.h включает extern объявления для верхней модели инициализируют, завершают и выполняют (выполняют) функции точки входа.

    extern void rtwdemo_comp_initialize(RT_MODEL_rtwdemo_comp_T *const
      rtwdemo_comp_M);
    
    extern void Run(RT_MODEL_rtwdemo_comp_T *const rtwdemo_comp_M);
    
  • Образец модели

    Заголовок файла slprj/ert/rtwdemo_func_dinteg/rtwdemo_func_dinteg.h включает extern объявления для функций точки входа образца модели.

    extern void rtwdemo_func_dinteg_initialize(const char_T **rt_errorStatus,
      RT_MODEL_rtwdemo_func_dinteg_T *const rtwdemo_func_dinteg_M);
    extern real_T rtwdemo_func_dinteg_multiinstfunc(RT_MODEL_rtwdemo_func_dinteg_T * 
      const rtwdemo_func_dinteg_M, const real_T rtu_u);
    extern void rtwdemo_func_dinteg_Start(RT_MODEL_rtwdemo_func_dinteg_T *const 
      rtwdemo_func_dinteg_M, const real_T *rtu_In1, const real_T *rtu_In2, real_T
      *rty_Out2, real_T *rty_Out1);
    

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

Сгенерируйте код С++ для модели.

  • Код функции для блока Simulink Function с мультиобразцами

    Когда вы помещаете масштабированный блок Simulink Function в модель-ссылку, которую вы используете несколько раз в другой модели, генератор кода помещает код функции в model.cpp файл для ссылочной модели. В данном примере генератор кода помещает код функции для multiinstfunc в slprj/ert/rtwdemo_func_dinteg/rtwdemo_func_dinteg_cpp.cpp.

    real_T rtwdemo_func_dintegModelClass::multiinstfunc(const real_T rtu_u)
    {
      real_T rtb_TmpLatchAtInOutport1;
      real_T rtb_TmpLatchAtIn2Outport1;
      real_T rty_y_0;
    
      rtb_TmpLatchAtInOutport1 = *rtwdemo_func_dinteg_cprtrtu_In1;
    
      rtb_TmpLatchAtIn2Outport1 = *rtwdemo_func_dinteg_cprtrtu_In2;
    
      *rtwdemo_func_dinteg_crtrty_Out2 = 2.0 * rtb_TmpLatchAtInOutport1;
    
      rtwdemo_func_dinteg_c_func_calc(rtb_TmpLatchAtIn2Outport1,
        rtwdemo_func_dinteg_crtrty_Out1);
    
      rty_y_0 = rtwdemo_func_dinteg_cpprtDW.DiscreteIntegrator_DSTATE;
    
      rtwdemo_func_dinteg_cpprtDW.DiscreteIntegrator_DSTATE += 0.1 * rtu_u;
      return rty_y_0;
    }
  • Код функции для блока Simulink Function, заданный в подсистеме

    Генератор кода помещает код функции для блока Simulink Function, который вы задаете в подсистеме model.cpp для модели, которая содержит подсистему. В данном примере генератор кода помещает код функции для func_calc в slprj/ert/rtwdemo_func_dinteg/rtwdemo_func_dinteg_cpp.cpp.

    void rtwdemo_func_dintegModelClass::rtwdemo_func_dinteg_c_func_calc(real_T rtu_u,
      real_T *rty_y)
    {
      rtwdemo_func_dinteg_cpprtDW.calcMem =
        rtwdemo_func_dinteg_cpprtDW.UnitDelay_DSTATE;
    
      *rty_y = rtwdemo_func_dinteg_cpprtDW.UnitDelay_DSTATE;
    
      rtwdemo_func_dinteg_cpprtDW.UnitDelay_DSTATE = rtu_u * 0.07;
    }
    
  • Структура, которая хранит данные мультиобразцов для переиспользуемых функций

    Генератор кода использует структуру, подобную модели реального времени (RT_MODEL) структура данных для хранения данных мультиобразцов, связанных со Reusable function. Генератор кода определяет структуру в slprj/ert/rtwdemo_func_dinteg/rtwdemo_func_dinteg_cpp.h.

    typedef struct rtwdemo_func_dinteg_cpp_tag_RTM rtwdemo_func_dinteg_cp_RT_MODEL;
    
  • Код инициализации для модели с мультиобразцами

    Для каждого образца ссылочной модели, который включает в себя один и тот же масштабированный блок Simulink Function, генератор кода производит инициализацию и код функции запуска. Одна копия кода инициализации определяется как slprj/ert/rtwdemo_func_dinteg/rtwdemo_func_dinteg_cpp.cpp.

    void rtwdemo_func_dintegModelClass::start(real_T *rtu_In1, real_T *rtu_In2,
      real_T *rty_Out2, real_T *rty_Out1)
    {
      rtwdemo_func_dinteg_cprtrtu_In1 = rtu_In1;
      rtwdemo_func_dinteg_cprtrtu_In2 = rtu_In2;
      rtwdemo_func_dinteg_crtrty_Out2 = rty_Out2;
      rtwdemo_func_dinteg_crtrty_Out1 = rty_Out1;
    }
    .
    .
    .
    void rtwdemo_func_dintegModelClass::initializeRTM()
    {
      (void) memset((void *)((&rtwdemo_func_dinteg_cpprtM)), 0,
                    sizeof(rtwdemo_func_dinteg_cp_RT_MODEL));
    }
    

    Код инициализации вызывается для каждого образца ссылочной модели, который содержит один и тот же блок Simulink Function. Этот код находится в файле rtwdemo_comp_cpp.cpp в папке сборки.

    .
    .
    .
    
    Instance1MDLOBJ0.initializeRTM();
    
    Instance1MDLOBJ0.setErrorStatusPointer(rtmGetErrorStatusPointer((&rtM)));
    Instance1MDLOBJ0.initialize();
    
    Instance2MDLOBJ1.initializeRTM();
    
    Instance2MDLOBJ1.setErrorStatusPointer(rtmGetErrorStatusPointer((&rtM)));
    	
    Instance1MDLOBJ0.start(&rtU.In2, &rtU.In3, &rtY.Out2, &rtY.Out3);
    
    Instance2MDLOBJ1.start(&rtwU.In4, &rtwU.In5, &rtY.Out4, &rtY.Out5);
    }
  • Декларация класса верхней модели

    Файл заголовка модели rtwdemo_comp_cpp.h включает объявление класса для верхней модели.

    class rtwdemo_compModelClass {
     public:
      ExtU rtU;
    
      ExtY rtY;
    
      void initialize();
    
      void Run();
    
      rtwdemo_compModelClass();
    
      ~rtwdemo_compModelClass();
    
      RT_MODEL * getRTM();
    
     private:
      RT_MODEL rtM;
    
      rtwdemo_func_dintegModelClass Instance1MDLOBJ0;
    
      rtwdemo_func_dintegModelClass Instance2MDLOBJ1;
    };
    
  • Образец модели

    Заголовок файла slprj/ert/rtwdemo_func_dinteg/rtwdemo_func_dinteg_cpp.h включает объявление класса для образца модели.

    class rtwdemo_func_dintegModelClass {
     public:
      real_T multiinstfunc(const real_T rtu_u);
    
      void start(real_T *rtu_In1, real_T *rtu_In2, real_T *rty_Out2, real_T
    	            *rty_Out1);
    
      rtwdemo_func_dintegModelClass();
    	
      ~rtwdemo_func_dintegModelClass();
    
      rtwdemo_func_dinteg_cp_RT_MODEL * getRTM();
    
      void initializeRTM();
    
      void setErrorStatusPointer(const char_T **rt_errorStatus);
    
     private:
      rtwdemo_func_dinteg_cpp_DW rtwdemo_func_dinteg_cpprtDW;
    
      const real_T *rtwdemo_func_dinteg_cprtrtu_In1;
      const real_T *rtwdemo_func_dinteg_cprtrtu_In2;
      real_T *rtwdemo_func_dinteg_crtrty_Out2;
      real_T *rtwdemo_func_dinteg_crtrty_Out1;
    
      rtwdemo_func_dinteg_cp_RT_MODEL rtwdemo_func_dinteg_cpprtM;
    
      void rtwdemo_func_dinteg_c_func_calc(real_T rtu_u, real_T *rty_y);
    };

Ограничения

Эти ограничения генерации кода применяются к экспорту функций моделям, которые включают в себя несколько образцы блока Simulink Function.

  • Вы должны задать параметр конфигурации модели Pass root-level I/O as равным Part of model data structure.

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

  • Вы не можете:

    • Сгенерируйте код, если модель export-function включает варианты модели.

    • Вызовите сгенерированный код из Stateflow® график.

    • Включите интерфейс обмена данными во режиме external mode.

Похожие темы