Чтобы сконфигурировать символьные размерности для Блоков 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