Запись Полностью Встроенные S-функции с mdlRTW Стандартной программой

Можно встроить более комплексные S-функции при помощи S-функции стандартная программа mdlRTW. Стандартная программа mdlRTW предоставляет процессу генерации кода больше информации о том, как S-функция должна быть встроена путем создания записи параметра ненастраиваемого параметра для использования с файлом TLC. Стандартная программа mdlRTW помещает информацию в файл model.rtw. Функция mdlRTW описана в текстовом файле matlabroot/simulink/src/sfuntmpl_doc.c.

Чтобы использовать функцию mdlRTW, предпримите шаги, чтобы создать S-функцию поиска прямого индекса. Интерполяционные таблицы являются наборами упорядоченных точек данных функции. Как правило, эти таблицы используют некоторую схему интерполяции для приближенных значений присоединенной функции между известными точками данных. Чтобы включить алгоритм интерполяционной таблицы в качестве примера в модель Simulink®, первый шаг должен записать S-функцию, которая выполняет алгоритм в mdlOutputs. Чтобы произвести самый эффективный код, следующий шаг должен создать соответствующий файл TLC, чтобы устранить вычислительные издержки и улучшить скорость вычислений поиска.

Продукт Simulink оказывает поддержку для двух поисков общего назначения 1D и 2D алгоритмы. Можно использовать эти алгоритмы, как они - или создают пользовательскую S-функцию интерполяционной таблицы, чтобы соответствовать требованиям. Можно создать 1D S-функцию поиска, sfun_directlook.c и его соответствующий встроенный файл sfun_directlook.tlc (см. Компилятор Выходного языка (Simulink Coder) для получения дополнительной информации). Вы можете:

  • Проверка на ошибки S-параметров-функции.

  • Информация о кэше для S-функции, которая не изменяется во время образцового выполнения.

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

  • Создайте файл TLC для S-функции, которая или полностью встраивает код интерполяционной таблицы или вызывает функцию обертки для алгоритма интерполяционной таблицы.

S-функция RTWdata

RTWdata является свойством блоков, которые могут использоваться целевым Языковым компилятором при встраивании S-функции. RTWdata является структурой векторов символов, которые можно присоединить к блоку. RTWdata сохранен с моделью и помещенный в файл model.rtw, когда вы генерируете код. Например, этот набор команд MATLAB®:

mydata.field1 = 'information for field1';
mydata.field2 = 'information for field2';
set_param(gcb,'RTWdata',mydata)
get_param(gcb,'RTWdata')

приводит к этому результату:

ans = 
 
    field1: 'information for field1'
    field2: 'information for field2'

Информация для связанного Блока s-function в файле model.rtw:

Block {
  Type                    "S-Function"
  RTWdata {
    field1                  "information for field1"
    field2                  "information for field2"
  }

Примечание

RTWdata сохранен в образцовом файле для S-функций, которые не соединяются с библиотекой. Однако RTWdata не является персистентным для Блоков s-function, которые соединяются с библиотекой.

Алгоритм интерполяционной таблицы прямого индекса

1D блок интерполяционной таблицы, обеспеченный в Библиотеке Simulink, использует интерполяцию или экстраполяцию когда вычислительные выходные параметры. В этом примере вы создаете интерполяционную таблицу, которая непосредственно индексирует выходной вектор (y-вектор-данных) на основе текущего входа (x-данные) точка.

Этот прямой 1D пример поиска вычисляет приближенное решение p (x) к частично известной функции f (x) в x=x0, пары точки определенных данных (x, y) в форме x-вектора-данных и y-вектора-данных. Для пары определенных данных (например, i'th пары), y_i = f (x_i). Это принято, что x-значения-данных монотонно увеличиваются. Если x0 вне области значений x-вектора-данных, первая или последняя точка возвращена.

Параметры к S-функции:

XData, YData, XEvenlySpaced

XData и YData удваивают векторы равной длины, представляющей значения неизвестной функции. XDataEvenlySpaced является скаляром, 0.0 для лжи и 1.0 для истины. Если вектор XData равномерно расположен с интервалами, XDataEvenlySpaced является 1.0, и более эффективный код сгенерирован.

График показывает, как параметры XData=[1:6] и YData=[1,2,7,4,5,9] обработаны. Например, если вход (x-значение) к Блоку s-function равняется 3, вывод (y-значение) равняется 7.

Пример интерполяционной таблицы прямого индекса

Улучшите интерполяционную таблицу путем встраивания S-функции прямого индекса с файлом TLC. Эта S-функция интерполяционной таблицы прямого индекса не требует файла TLC. Пример использует файл TLC для S-функции интерполяционной таблицы прямого индекса, чтобы уменьшать размер кода и эффективность увеличения сгенерированного кода.

Реализация алгоритма прямого индекса со встроенным файлом TLC требует S-функции основной модуль, sfun_directlook.c и соответствующий модуль lookup_index.c. Модуль lookup_index.c содержит функцию GetDirectLookupIndex, которая используется, чтобы определить местоположение индекса в XData для текущего входного значения x, когда XData неравномерно расположен с интервалами. Стандартная программа GetDirectLookupIndex называется от S-функции и сгенерированного кода. Пример использует концепцию обертки для совместного использования кода C/C++ между файлами MEX Simulink и сгенерированным кодом.

Если XData равномерно расположен с интервалами, то и S-функция, основной модуль и сгенерированный код содержат алгоритм поиска, чтобы вычислить y-значение данного x-значения, потому что алгоритм короток.

Встроенным файлом TLC является sfun_directlook.tlc, который используется, чтобы или выполнить вызов обертки или встроить оптимальный код C/C++ для S-функции. (См. пример в mdlRTW Использовании (Simulink Coder)).

Обработка ошибок

В sfun_directlook.tlc стандартная программа mdlCheckParameters проверяет что:

  • Новые установки параметров допустимы.

  • XData и YData являются векторами той же длины, содержащей действительные, конечные числа.

  • XDataEvenlySpaced является скаляром.

  • Вектор XData является монотонно увеличивающимся вектором и равномерно распределенный.

Функция mdlInitializeSizes явным образом вызывает mdlCheckParameters после того, как это проверяет, что количество параметров передало S-функции. После того, как механизм Simulink вызывает mdlInitializeSizes, он затем вызывает mdlCheckParameters каждый раз, когда вы изменяете параметры или переоцениваете их.

Пользовательское кэширование данных

В sfun_directlook.tlc стандартная программа mdlStart показывает, как кэшировать информацию, которая не изменяется во время симуляции или в то время как сгенерированный код выполняется. Пример кэширует значение параметра XDataEvenlySpaced в UserData, поле SimStruct. Следующая строка в mdlInitializeSizes дает механизму Simulink команду запрещать изменения в XDataEvenlySpaced.

ssSetSFcnParamTunable(S, iParam, SS_PRM_NOT_TUNABLE);

Во время выполнения mdlOutputs получает доступ к значению XDataEvenlySpaced от UserData вместо того, чтобы вызвать функцию MATLAB API mxGetPr.

Использование mdlRTW

Генератор кода вызывает стандартную программу mdlRTW при генерации файла model.rtw. Чтобы произвести оптимальный код для вашей модели Simulink, можно добавить информацию в файл model.rtw о режиме, в котором действует Блок s-function.

Пример добавляет установки параметров в файл model.rtw. Установки параметров не изменяются во время выполнения. В этом случае S-параметр-функции XDataEvenlySpaced не может измениться во время выполнения (ssSetSFcnParamTunable был задан как ложь (0) для него в mdlInitializeSizes). Установка параметра (XSpacing) использует функциональный ssWriteRTWParamSettings.

Поскольку xData и yData указаны как параметры периода выполнения в mdlSetWorkWidths, генератор кода пишет в файл model.rtw автоматически.

Прежде, чем исследовать S-функцию и встроенный файл TLC, рассмотрите сгенерированный код для этой модели.

Образцовое использование равномерно расположило с интервалами XData в главном Блоке s-function и неравномерно расположило с интервалами XData в нижнем Блоке s-function. При создании этой модели задайте следующие команды для каждого Блока s-function.

set_param('sfun_directlook_ex/S-Function','SFunctionModules','lookup_index')
set_param('sfun_directlook_ex/S-Function1','SFunctionModules','lookup_index')

Процесс сборки использует модуль lookup_index.c при создании исполняемого файла.

При генерации кода для этой модели генератор кода использует S-функцию метод mdlRTW, чтобы сгенерировать файл model.rtw со значением EvenlySpaced для параметра XSpacing для главного Блока s-function и значения UnEvenlySpaced для параметра XSpacing для нижнего Блока s-function. TLC-файл использует значение XSpacing, чтобы определить что алгоритм включать в сгенерированный код. Сгенерированный код содержит алгоритм поиска, когда XData равномерно расположен с интервалами, но вызывает стандартную программу GetDirectLookupIndex, когда XData неравномерно расположен с интервалами. Сгенерированный код model.c или model.cpp для модели интерполяционной таблицы в качестве примера подобен этому коду:

/*
 * sfun_directlook_ex.c
 * 
 * Code generation for Simulink model 
 * "sfun_directlook_ex.slx".
 *
...
 */

#include "sfun_directlook_ex.h"
#include "sfun_directlook_ex_private.h"

/* External outputs (root outports fed by signals with auto storage) */
ExtY_sfun_directlook_ex_T sfun_directlook_ex_Y;

/* Real-time model */
RT_MODEL_sfun_directlook_ex_T sfun_directlook_ex_M_;
RT_MODEL_sfun_directlook_ex_T *const sfun_directlook_ex_M =
  &sfun_directlook_ex_M_;

/* Model output function */
void sfun_directlook_ex_output(void)
{
  /* local block i/o variables */
  real_T rtb_SFunction;
  real_T rtb_SFunction1;

  /* Sin: '<Root>/Sine Wave' */
  rtb_SFunction1 = sin(sfun_directlook_ex_M->Timing.t[0]);
  
/* Code that is inlined for the top S-function block in the 
   * sfun_directlook_ex model
   */
  /* S-Function (sfun_directlook): '<Root>/S-Function' */
  {
    const real_T *xData = sfun_directlook_ex_ConstP.SFunction_XData;
    const real_T *yData = sfun_directlook_ex_ConstP.SFunction_YData;
    real_T spacing = xData[1] - xData[0];
    if (rtb_SFunction1 <= xData[0] ) {
      rtb_SFunction = yData[0];
    } else if (rtb_SFunction1 >= yData[20] ) {
      rtb_SFunction = yData[20];
    } else {
      int_T idx = (int_T)( ( rtb_SFunction1 - xData[0] ) / spacing );
      rtb_SFunction = yData[idx];
    }
  }

  /* Outport: '<Root>/Out1' */
  sfun_directlook_ex_Y.Out1 = rtb_SFunction;

/* Code that is inlined for the bottom S-function block in the 
   * sfun_directlook_ex model
   */
  /* S-Function (sfun_directlook): '<Root>/S-Function1' */
  {
    const real_T *xData = sfun_directlook_ex_ConstP.SFunction1_XData;
    const real_T *yData = sfun_directlook_ex_ConstP.SFunction1_YData;
    int_T idx;
    idx = GetDirectLookupIndex(xData, 5, rtb_SFunction1);
    rtb_SFunction1 = yData[idx];
  }

  /* Outport: '<Root>/Out2' */
  sfun_directlook_ex_Y.Out2 = rtb_SFunction1;
}

/* Model update function */
void sfun_directlook_ex_update(void)
{
  /* signal main to stop simulation */
  {                                    /* Sample time: [0.0s, 0.0s] */
    if ((rtmGetTFinal(sfun_directlook_ex_M)!=-1) &&
        !((rtmGetTFinal(sfun_directlook_ex_M)-sfun_directlook_ex_M->Timing.t[0])
          > sfun_directlook_ex_M->Timing.t[0] * (DBL_EPSILON))) {
      rtmSetErrorStatus(sfun_directlook_ex_M, "Simulation finished");
    }
  }

  /* Update absolute time for base rate */
  /* The "clockTick0" counts the number of times the code of this task has
   * been executed. The absolute time is the multiplication of "clockTick0"
   * and "Timing.stepSize0". Size of "clockTick0" ensures timer will not
   * overflow during the application lifespan selected.
   * Timer of this task consists of two 32 bit unsigned integers.
   * The two integers represent the low bits Timing.clockTick0 and the high bits
   * Timing.clockTickH0. When the low bit overflows to 0, the high bits increment.
   */
  if (!(++sfun_directlook_ex_M->Timing.clockTick0)) {
    ++sfun_directlook_ex_M->Timing.clockTickH0;
  }

  sfun_directlook_ex_M->Timing.t[0] = sfun_directlook_ex_M->Timing.clockTick0 *
    sfun_directlook_ex_M->Timing.stepSize0 +
    sfun_directlook_ex_M->Timing.clockTickH0 *
    sfun_directlook_ex_M->Timing.stepSize0 * 4294967296.0;
}
...

Похожие темы