Можно использовать следующий SimStruct
макросы в mdlInitializeSizes
метод, чтобы задать осциллограф и возможность многократного использования памяти, используемой для портов ввода и вывода вашей S-функции:
ssSetInputPortOptimOpts
: Задайте осциллограф и возможность многократного использования памяти, выделенной порту S-входного-параметра-функции.
ssSetOutputPortOptimOpts
: Задайте осциллограф и возможность многократного использования памяти, выделенной выходному порту S-функции.
ssSetInputPortOverWritable
: Задайте, может ли один из входных портов вашей S-функции быть перезаписан одним из ее выходных портов.
ssSetOutputPortOverwritesInputPort
: Задайте, может ли выходной порт совместно использовать свой буфер памяти с входным портом.
Вы объявляете ввод или вывод как локальный или глобальный, и указываете на его возможность многократного использования путем передачи одной из следующих четырех опций к ssSetInputPortOptimOpts
и ssSetOutputPortOptimOpts
макросы:
SS_NOT_REUSABLE_AND_GLOBAL
: Указывает, что порты ввода и вывода хранятся в отдельных ячейках памяти в глобальной структуре ввода и вывода блока.
SS_NOT_REUSABLE_AND_LOCAL
: Указывает, что генератор кода может объявить отдельные локальные переменные для портов ввода и вывода.
SS_REUSABLE_AND_LOCAL
: Указывает, что генератор кода может снова использовать одну локальную переменную для этих портов ввода и вывода.
SS_REUSABLE_AND_GLOBAL
: Указывает, что эти порты ввода и вывода хранятся в одном элементе в глобальной структуре ввода и вывода блока.
Примечание
При отмечании порта ввода или вывода, когда локальная переменная не подразумевает, что генератор кода использует локальную переменную в сгенерированном коде. Если ваша S-функция получает доступ к вводам и выводам только в ее mdlOutputs
стандартная программа, генератор кода объявляет вводы и выводы как локальные переменные. Однако, если вводы и выводы используются в другом месте в S-функции, генератор кода включает их в глобальную структуру ввода и вывода блока.
Установка возможности многократного использования указывает, может ли память, сопоставленная с портом ввода или вывода, быть перезаписана. К порту memory ввода и вывода повторного использования:
Укажите, что порты являются допускающим повторное использование использованием любого SS_REUSABLE_AND_LOCAL
или SS_REUSABLE_AND_GLOBAL
опция в ssSetInputPortOptimOpts
и ssSetOutputPortOptimOpts
макросы.
Укажите, что память входного порта является сверхперезаписываемым использованием ssSetInputPortOverWritable
.
Если ваша S-функция имеет несколько портов ввода и вывода, используйте ssSetOutputPortOverwritesInputPort
указать, какие выходные и входные порты совместно используют память.
Следующий пример показывает, как различный осциллограф и настройки возможности многократного использования влияют на сгенерированный код. Следующая модель содержит Блок s-function, указывающий на S-функцию MEX C
, который моделирует прямую 1D интерполяционную таблицу.matlabroot
/toolbox/simulink/simdemos/simfeatures/src/sfun_directlook.c
mdlInitializeSizes
S-функции метод объявляет входной порт, столь же допускающий повторное использование, локальный, и сверхперезаписываемый и выходной порт как допускающий повторное использование и локальный, можно следующим образом:
static void mdlInitializeSizes(SimStruct *S) { /* snip */ ssSetInputPortOptimOpts(S, 0, SS_REUSABLE_AND_LOCAL); ssSetInputPortOverWritable(S, 0, TRUE); /* snip */ ssSetOutputPortOptimOpts(S, 0, SS_REUSABLE_AND_LOCAL); /* snip */ }
Сгенерированный код для этой модели хранит сигналы ввода и вывода в одной локальной переменной rtb_SFunction
, как показано в следующей выходной функции:
static void sl_directlook_output(int_T tid) { /* local block i/o variables */ real_T rtb_SFunction[2]; /* Sin: '<Root>/Sine Wave' */ rtb_SFunction[0] = sin(((real_T)sl_directlook_DWork.counter[0] + sl_directlook_P.SineWave_Offset) * 2.0 * 3.1415926535897931E+000 / sl_directlook_P.SineWave_NumSamp) * sl_directlook_P.SineWave_Amp[0] + sl_directlook_P.SineWave_Bias; rtb_SFunction[1] = sin(((real_T)sl_directlook_DWork.counter[1] + sl_directlook_P.SineWave_Offset) * 2.0 * 3.1415926535897931E+000 / sl_directlook_P.SineWave_NumSamp) * sl_directlook_P.SineWave_Amp[1] + sl_directlook_P.SineWave_Bias; /* S-Function Block: <Root>/S-Function */ { const real_T *xData = &sl_directlook_P.SFunction_XData[0]; const real_T *yData = &sl_directlook_P.SFunction_YData [0]; real_T spacing = xData[1] - xData[0]; if (rtb_SFunction[0] <= xData[0] ) { rtb_SFunction[0] = yData[0]; } else if (rtb_SFunction[0] >= yData[20] ) { rtb_SFunction[0] = yData[20]; } else { int_T idx = (int_T)( ( rtb_SFunction[0] - xData[0] ) / spacing ); rtb_SFunction[0] = yData[idx]; } if (rtb_SFunction[1] <= xData[0] ) { rtb_SFunction[1] = yData[0]; } else if (rtb_SFunction[1] >= yData[20] ) { rtb_SFunction[1] = yData[20]; } else { int_T idx = (int_T)( ( rtb_SFunction[1] - xData[0] ) / spacing ); rtb_SFunction[1] = yData[idx]; } } /* Outport: '<Root>/Out1' */ sl_directlook_Y.Out1[0] = rtb_SFunction[0]; sl_directlook_Y.Out1[1] = rtb_SFunction[1]; UNUSED_PARAMETER(tid); }
Эта таблица показывает изменения кода, сгенерированного для этой модели при использовании типовой цели в реальном времени (GRT). Каждая строка объясняет различную установку для осциллографа и возможности многократного использования портов ввода и вывода S-функции.
Осциллограф и возможность многократного использования | S-функция mdlInitializeSizes код | Сгенерированный код |
---|---|---|
Входные параметры: Локальный, допускающий повторное использование, сверхперезаписываемый Выходные параметры : Локальный, допускающий повторное использование |
ssSetInputPortOptimOpts(S, 0, SS_REUSABLE_AND_LOCAL); ssSetInputPortOverWritable(S, 0, TRUE); ssSetOutputPortOptimOpts(S, 0, SS_REUSABLE_AND_LOCAL); |
/* local block i/o variables */ real_T rtb_SFunction[2]; |
Входные параметры: Глобальная переменная, допускающая повторное использование, сверхперезаписываемая Выходные параметры : Глобальная переменная, допускающая повторное использование |
ssSetInputPortOptimOpts(S, 0, SS_REUSABLE_AND_GLOBAL); ssSetInputPortOverWritable(S, 0, TRUE); ssSetOutputPortOptimOpts(S, 0, SS_REUSABLE_AND_GLOBAL); |
/* Block signals (auto storage) */ typedef struct { real_T SFunction[2]; } BlockIO_sl_directlook;
/* Sin: '<Root>/Sine Wave' */ sl_directlook_B.SFunction[0] = sin ... /* snip */ /*S-Function Block:<Root>/S-Function*/ { const real_T *xData = &sl_directlook_P.SFunction_XData[0] |
Входные параметры: Локальный, не допускающий повторное использование Выходные параметры : Локальный, не допускающий повторное использование |
ssSetInputPortOptimOpts(S, 0, SS_NOT_REUSABLE_AND_LOCAL); ssSetInputPortOverWritable(S, 0, FALSE); ssSetOutputPortOptimOpts(S, 0, SS_NOT_REUSABLE_AND_LOCAL); |
/* local block i/o variables */ real_T rtb_SineWave[2]; real_T rtb_SFunction[2]; |
Входные параметры: Глобальная переменная, не допускающая повторное использование Выходные параметры : Глобальная переменная, не допускающая повторное использование |
ssSetInputPortOptimOpts(S, 0, SS_NOT_REUSABLE_AND_GLOBAL); ssSetInputPortOverWritable(S, 0, FALSE); ssSetOutputPortOptimOpts(S, 0, SS_NOT_REUSABLE_AND_GLOBAL); |
/* Block signals (auto storage) */ typedef struct { real_T SineWave[2]; real_T SFunction[2]; } BlockIO_sl_directlook;
/* Sin: '<Root>/Sine Wave' */ sl_directlook_B.SineWave[0] = sin ... /* snip */ /*S-Function Block:<Root>/S-Function*/ { const real_T *xData = &sl_directlook_P.SFunction_XData[0] |
Чтобы проверять, происходит ли повторное использование S-входного-параметра-функции или буфера вывода, можно использовать LibBlockInputSignalBufferDstPort
функция.