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

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

Генератор кода производит повторно используемый функциональный код, когда вы конфигурируете a:

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

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

Прежде и в то время как вы проектируете свою модель, рассмотрите:

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

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

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

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

  • Функции должны соединиться с внешним вводом-выводом?

  • Необходимо ли регистрировать функциональный выход?

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

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

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

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

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

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

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

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

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

Сконфигурируйте Функциональные блоки Simulink путем установки параметров для функциональной Триггерной Блокировки порта. Для генератора кода, чтобы произвести повторно используемый код из Функциональных блоков Simulink:

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

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

В примере, имени функции для Функциональных блоков Simulink в двух экземплярах model rtwdemo_func_dinteg, на который ссылаются, задан как multiinstfunc.

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

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

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

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

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

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

Настройка подсистемы

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

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

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

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

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

  • В диалоговом окне Block Parameters, установленный параметр Model name к имени файла модели, на которое ссылаются. В данном примере именем модели является rtwdemo_func_dinteg.slx.

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

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

Опционально, можно настроить интерфейсы функции точки входа модели. Можно задать имена функций точки входа. Для выполнения (шаг) функционирует точка входа, можно сконфигурировать имя функции и аргументы. Пользовательские интерфейсы функции точки входа могут минимизировать изменения в существующем внешнем коде, который вы интегрируете со сгенерированным кодом. Пример использует функциональные интерфейсы по умолчанию. Смотрите Настраивают Интерфейсы Функции Точки входа для Simulink Функциональные и Функциональные Блоки Вызывающей стороны (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.

Опционально, можно настроить интерфейсы функции точки входа модели. Можно задать имена функций точки входа. Для выполнения (шаг) функционирует точка входа, можно сконфигурировать имя функции и аргументы. Пользовательские интерфейсы функции точки входа могут минимизировать изменения в существующем внешнем коде, который вы интегрируете со сгенерированным кодом. Пример использует функциональные интерфейсы по умолчанию. Смотрите Настраивают Интерфейсы Функции Точки входа для Simulink Функциональные и Функциональные Блоки Вызывающей стороны (Embedded Coder).

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

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

  • Функциональный код для мультиэкземпляра Функциональный блок Simulink

    Когда вы помещаете ограниченный по объему Функциональный блок Simulink в модель, на которую ссылаются, которую вы используете многократно в другой модели, генератор кода помещает функциональный код в modelC файл для модели, на которую ссылаются. В данном примере генератор кода помещает функциональный код для 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 задан в подсистеме

    Генератор кода помещает функциональный код для Функционального блока Simulink, который вы задаете в подсистеме в modelC файл для модели, которая содержит подсистему. В данном примере генератор кода помещает функциональный код для 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, генератор кода производит код функции инициализации и запуска. Одна копия кода инициализации задана в 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. Тот код находится в файле 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

    Когда вы помещаете ограниченный по объему Функциональный блок Simulink в модель, на которую ссылаются, которую вы используете многократно в другой модели, генератор кода помещает функциональный код в 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 задан в подсистеме

    Генератор кода помещает функциональный код для Функционального блока Simulink, который вы задаете в подсистеме в 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, генератор кода производит код функции инициализации и запуска. Одна копия кода инициализации задана в 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. Тот код находится в файле 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.

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

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

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

    • Сгенерируйте код, если модель экспорта функций включает варианты модели.

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

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

Похожие темы