Чтобы сконфигурировать символьные размерности для Блоков s-function, можно использовать следующие функции C/C++. Можно сконфигурировать S-функции, чтобы поддержать прямое распространение, обратное распространение или прямое и обратное распространение символьных размерностей в процессе моделирования.
Многие из этих функций возвращают переменную SymbDimsId. SymbDimsId уникальное целочисленное значение. Это значение соответствует каждой символьной спецификации размерности, которую вы создаете, или результат математической операции, которую вы выполняете с символьными размерностями.
| S-функции C/C++ | Цель |
|---|---|
Задайте, поддерживает ли S-функция символьные размерности. | |
Задайте символьные размерности входного порта и как те размерности распространяют вперед. | |
Задайте символьные размерности выходного порта и как те размерности распространяют назад. | |
Создайте | |
Создайте | |
Создайте | |
Создайте | |
Создайте | |
Создайте | |
Создайте | |
Создайте | |
Получите количество размерностей для | |
Получите | |
Установите предварительно скомпилированный | |
Получите скомпилированный | |
Установите скомпилированный | |
Установите предварительно скомпилированный | |
Получите скомпилированный | |
Установите скомпилированный | |
Установите скомпилированный |
Модель ex_msymbdims_sfcn_one содержит S-функцию, которая вычитает символьную размерность B от символьной входной размерности, A + B. Модель поддерживает прямое распространение, потому что символьные размерности выходных портов установлены. Модель не поддерживает обратное распространение символьных размерностей, потому что скомпилированные символьные размерности входных портов не установлены.
model='ex_msymbdims_sfcn_one';
open_system(model);

sfun_symbdims_sfcn_one.c файл содержит этот код.
type sfun_symbdims_sfcn_one.c
/* Copyright 2014 The MathWorks, Inc. */
#define S_FUNCTION_NAME sfun_symbdims_sfcn_one
#define S_FUNCTION_LEVEL 2
#include "simstruc.h"
#include <assert.h>
/* Function: mdlInitializeSizes ===============================================
* Abstract:
* Setup sizes of the various vectors.
*/
static void mdlInitializeSizes(SimStruct *S)
{
ssSetNumSFcnParams(S, 0); /* Number of expected parameters */
ssSetNumContStates(S, 0);
ssSetNumDiscStates(S, 0);
if (!ssSetNumInputPorts(S, 1)) return;
ssSetInputPortDirectFeedThrough(S, 0, 1);
ssSetInputPortDimensionInfo(S, 0, DYNAMIC_DIMENSION);
ssSetInputPortRequiredContiguous(S, 0, 1);
if (!ssSetNumOutputPorts(S,1)) return;
ssSetOutputPortDimensionInfo(S, 0, DYNAMIC_DIMENSION);
ssSetNumSampleTimes(S, 1);
ssSetNumRWork(S, 0);
ssSetNumIWork(S, 0);
ssSetNumPWork(S, 0);
ssSetNumModes(S, 0);
ssSetNumNonsampledZCs( S, 0);
ssAllowSignalsWithMoreThan2D(S);
ssSetOptions(S, SS_OPTION_EXCEPTION_FREE_CODE);
ssSetSymbolicDimsSupport(S, true);
}
/*If underspecified for propagation, say i/o are scalars.*/
#if defined(MATLAB_MEX_FILE)
#define MDL_SET_DEFAULT_PORT_DIMENSION_INFO
static void mdlSetDefaultPortDimensionInfo(SimStruct *S)
{
if( (ssGetOutputPortWidth(S, 0) == DYNAMICALLY_SIZED)
&& (ssGetInputPortWidth(S, 0) == DYNAMICALLY_SIZED) ) {
ssSetOutputPortMatrixDimensions(S, 0, 1, 1 );
}
}
#endif
#if defined(MATLAB_MEX_FILE)
#define MDL_SET_INPUT_PORT_SYMBOLIC_DIMENSIONS
static void mdlSetInputPortSymbolicDimensions(SimStruct* S,
int_T portIndex, SymbDimsId symbDimsId)
{
assert(0 == portIndex);
// Set the compiled input symbolic dimension.
ssSetCompInputPortSymbolicDimsId(S, portIndex, symbDimsId);
const SymbDimsId symbolId = ssRegisterSymbolicDimsString(S, "B");
const SymbDimsId outputDimsId =
ssRegisterSymbolicDimsMinus(S, symbDimsId, symbolId);
ssSetCompOutputPortSymbolicDimsId(S, portIndex, outputDimsId);
}
#endif
#if defined(MATLAB_MEX_FILE)
#define MDL_SET_OUTPUT_PORT_SYMBOLIC_DIMENSIONS
static void mdlSetOutputPortSymbolicDimensions(SimStruct *S,
int_T portIndex, SymbDimsId symbDimsId)
{
assert(0 == portIndex);
// The input dimensions are not set, so this S-function only
// supports forward propagation.
ssSetCompOutputPortSymbolicDimsId(S, portIndex, symbDimsId);
}
#endif
/* Function: mdlInitializeSampleTimes =========================================
* Abstract:
* Specify that we inherit our sample time from the driving block.
* However, we don't execute in minor steps.
*/
static void mdlInitializeSampleTimes(SimStruct *S)
{
ssSetSampleTime(S, 0, INHERITED_SAMPLE_TIME);
ssSetOffsetTime(S, 0, 0.0);
ssSetModelReferenceSampleTimeDefaultInheritance(S);
}
/* Function: mdlOutputs =======================================================
* Abstract:
* y=u';
*/
static void mdlOutputs(SimStruct *S, int_T tid)
{
}
/* Function: mdlTerminate =====================================================
* Abstract:
* No termination needed, but we are required to have this routine.
*/
static void mdlTerminate(SimStruct *S)
{
UNUSED_ARG(S); /* unused input argument */
}
#ifdef MATLAB_MEX_FILE /* Is this file being compiled as a MEX-file? */
#include "simulink.c" /* MEX-file interface mechanism */
#else
#include "cg_sfun.h" /* Code generation registration function */
#endif
Simulink.Parameter object s A и B содержит эти определения.
type definitions.txt
A = Simulink.Parameter; A.DataType = 'int32'; A.Value = 6; A.Min=5; A.Max=7; A.CoderInfo.StorageClass = 'Custom'; A.CoderInfo.CustomStorageClass = 'ImportedDefine'; A.CoderInfo.CustomAttributes.HeaderFile = 'ImportedDefinitions.h'; B = Simulink.Parameter; B.DataType = 'int32'; B.Value = 10; B.Min=9; B.Max=11; B.CoderInfo.StorageClass = 'Custom'; B.CoderInfo.CustomStorageClass = 'ImportedDefine'; B.CoderInfo.CustomAttributes.HeaderFile = 'ImportedDefinitions.h';
ImportedDefinitions заголовочный файл содержит этот код.
type ImportedDefinitions.h
/* Copyright 2014 The MathWorks, Inc. */ #ifndef _IMPORTEDDEFINITIONS_H_ #define _IMPORTEDDEFINITIONS_H_ #define A 6 #define B 10 #endif
В диалоговом окне Configuration Paramters панель Пользовательского кода содержит #include "ImportedDefinitions.h" оператор.
sfun_symbdims_sfcn_one S-функция встраивается, таким образом, файл TLC с этим кодом должен присутствовать на пути с моделью и другими вспомогательными файлами.
type sfun_symbdims_sfcn_one.tlc
%implements "sfun_symbdims_sfcn_one" "C"
%function BlockInstanceSetup(block, system) void
%endfunction
%% Function: BlockOutputSignal =================================================
%function BlockOutputSignal(block,system,portIdx,ucv,lcv,idx,retType) void
%endfunction
%% Function: Outputs ===========================================================
%%
%function Outputs(block, system) Output
%assign rollVars = ["U", "Y"]
%roll idx = RollRegions, lcv = RollThreshold, block, "Roller", rollVars
%%
%assign u = LibBlockInputSignal( 0, "", lcv, idx)
%assign y = LibBlockOutputSignal(0, "", lcv, idx)
%<y> = %<u>;
%endroll
%endfunction %% Outputs
Чтобы сгенерировать MEX-функцию, в командной строке, вводят эту команду:
mex sfun_symbdims_sfcn_one.c
Building with 'gcc'. MEX completed successfully.
Сгенерируйте код для модели.
currentDir=pwd; slbuild(model);
### Starting build procedure for: ex_msymbdims_sfcn_one ### Successful completion of build procedure for: ex_msymbdims_sfcn_one Build Summary Top model targets built: Model Action Rebuild Reason ====================================================================================================== ex_msymbdims_sfcn_one 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 6.9991s
Просмотрите сгенерированный код для модели. ex_msymbdims_sfcn_one_step функция содержит этот код. Код S-функции установлен встроенный и символьные размерности A, и B находятся в сгенерированном коде.
cfile=fullfile(currentDir, 'ex_msymbdims_sfcn_one_ert_rtw','ex_msymbdims_sfcn_one.c'); rtwdemodbtype(cfile,'/* Model step', '/* Model initialize', 1, 0);
/* Model step function */
void ex_msymbdims_sfcn_one_step(void)
{
int32_T i;
/* Gain: '<Root>/Gain' incorporates:
* Concatenate: '<Root>/Matrix Concatenate'
* Inport: '<Root>/In1'
*/
for (i = 0; i < A; i++) {
ex_msymbdims_sfcn_one_B.MatrixConcatenate[i] = 2.0 *
ex_msymbdims_sfcn_one_U.In1[i];
}
/* End of Gain: '<Root>/Gain' */
/* Gain: '<Root>/Gain2' incorporates:
* Concatenate: '<Root>/Matrix Concatenate'
* Inport: '<Root>/In2'
*/
for (i = 0; i < B; i++) {
ex_msymbdims_sfcn_one_B.MatrixConcatenate[A + i] = 2.0 *
ex_msymbdims_sfcn_one_U.In2[i];
}
/* End of Gain: '<Root>/Gain2' */
/* S-Function (sfun_symbdims_sfcn_one): '<Root>/Minus' incorporates:
* Outport: '<Root>/Out1'
*/
{
int_T i1;
const real_T *u0 = &ex_msymbdims_sfcn_one_B.MatrixConcatenate[0];
real_T *y0 = &ex_msymbdims_sfcn_one_Y.Out1[0];
for (i1=0; i1 < ((A + B)); i1++) {
y0[i1] = u0[i1];
}
}
}
Закройте модель
bdclose(model);
Эта S-функция транспонирует две символьных размерности. Это поддерживает прямое и обратное распространение символьных размерностей, потому что скомпилированная символьная размерность обоих порты ввода и вывода установлена.
static void mdlInitializeSizes(SimStruct *S)
{
// Enable symbolic dimensions for the s-function.
ssSetSymbolicDimsSupport(S, true);
}
#if defined(MATLAB_MEX_FILE)
#define MDL_SET_INPUT_PORT_SYMBOLIC_DIMENSIONS
static void mdlSetInputPortSymbolicDimensions(SimStruct* S,
int_T portIndex, SymbDimsId symbDimsId)
{
assert(0 == portIndex);
ssSetCompInputPortSymbolicDimsId(S, portIndex, symbDimsId);
assert(2U == ssGetNumSymbolicDims(S, symbDimsId));
if (SL_INHERIT ==
ssGetCompOutputPortSymbolicDimsId(S, portIndex)) {
const SymbDimsId idVec[] = {
ssGetSymbolicDim(S, symbDimsId, 1),
ssGetSymbolicDim(S, symbDimsId, 0)};
// Register the transposed dimensions.
// Set the output symbolic dimension to the resulting id.
const SymbDimsId outputDimsId =
ssRegisterSymbolicDims(S, idVec, 2U);
ssSetCompOutputPortSymbolicDimsId(S, portIndex,
outputDimsId);
}
}
#endif
#if defined(MATLAB_MEX_FILE)
#define MDL_SET_OUTPUT_PORT_SYMBOLIC_DIMENSIONS
static void mdlSetOutputPortSymbolicDimensions(SimStruct *S,
int_T portIndex, SymbDimsId symbDimsId)
{
assert(0 == portIndex);
ssSetCompOutputPortSymbolicDimsId(S, portIndex, symbDimsId);
assert(2U == ssGetNumSymbolicDims(S, symbDimsId));
if (SL_INHERIT ==
ssGetCompInputPortSymbolicDimsId(S, portIndex)) {
const SymbDimsId idVec[] = {
ssGetSymbolicDim(S, symbDimsId, 1),
ssGetSymbolicDim(S, symbDimsId, 0)};
const SymbDimsId inputDimsId =
ssRegisterSymbolicDims(S, idVec, 2U);
// Register the transposed dimensions.
// Set the input symbolic dimension to the resulting id.
ssSetCompInputPortSymbolicDimsId(S, portIndex, inputDimsId);
}
}
#endif