Simulink Guide (Matlab)
Simulink Guide (Matlab)
Modeling
Simulation
Implementation
Writing S-Functions
Version 4
How to Contact The MathWorks:
www.mathworks.com Web
comp.soft-sys.matlab Newsgroup
508-647-7000 Phone
508-647-7001 Fax
For contact information about worldwide offices, see the MathWorks Web site.
Writing S-Functions
COPYRIGHT 1998 - 2001 by The MathWorks, Inc.
The software described in this document is furnished under a license agreement. The software may be used
or copied only under the terms of the license agreement. No part of this manual may be photocopied or repro-
duced in any form without prior written consent from The MathWorks, Inc.
FEDERAL ACQUISITION: This provision applies to all acquisitions of the Program and Documentation by
or for the federal government of the United States. By accepting delivery of the Program, the government
hereby agrees that this software qualifies as "commercial" computer software within the meaning of FAR
Part 12.212, DFARS Part 227.7202-1, DFARS Part 227.7202-3, DFARS Part 252.227-7013, and DFARS Part
252.227-7014. The terms and conditions of The MathWorks, Inc. Software License Agreement shall pertain
to the government’s use and disclosure of the Program and Documentation, and shall supersede any
conflicting contractual terms or conditions. If this license fails to meet the government’s minimum needs or
is inconsistent in any respect with federal procurement law, the government agrees to return the Program
and Documentation, unused, to MathWorks.
MATLAB, Simulink, Stateflow, Handle Graphics, and Real-Time Workshop are registered trademarks, and
Target Language Compiler is a trademark of The MathWorks, Inc.
Other product or brand names are trademarks or registered trademarks of their respective holders.
Printing History: October 1998 First printing Revised for Simulink 3.0 (Release 11)
November 2000 Second printing Revised for Simulink 4.0 (Release 12)
June 2001 Online only Revised for Simulink 4.1 (Release 12.1)
Contents
Overview of S-Functions
1
Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1-2
What Is an S-Function? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1-2
Using S-Functions in Models . . . . . . . . . . . . . . . . . . . . . . . . . . . 1-2
Passing Parameters to S-Functions . . . . . . . . . . . . . . . . . . . . . . 1-3
When to Use an S-Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1-5
How S-Functions Work . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1-5
Implementing S-Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1-9
S-Function Concepts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1-11
S-Function Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1-16
Writing M S-Functions
2
Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-2
S-Function Arguments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-2
S-Function Outputs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-3
Defining S-Function Block Characteristics . . . . . . . . . . . . . . . . 2-4
Processing S-Function Parameters . . . . . . . . . . . . . . . . . . . . . . 2-5
A Simple M-File S-Function Example . . . . . . . . . . . . . . . . . . . . 2-5
i
Writing S-Functions in C
3
Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-2
Creating C MEX S-Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-3
ii Contents
Making C++ Objects Persistent . . . . . . . . . . . . . . . . . . . . . . . . . 4-7
iii
Inline Code Generation Example . . . . . . . . . . . . . . . . . . . . . . . . 6-6
iv Contents
Sample Times . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7-16
Block-Based Sample Times . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7-16
Port-Based Sample Times . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7-19
Specifying the Number of Sample Times in mdlInitializeSizes 7-20
Hybrid Block-Based and Port-Based Sample Times . . . . . . . . 7-20
Multirate S-Function Blocks . . . . . . . . . . . . . . . . . . . . . . . . . . . 7-21
Synchronizing Multirate S-Function Blocks . . . . . . . . . . . . . . 7-22
v
Noninlined S-Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8-7
S-Function Module Names for Real-Time Workshop Builds . . . 8-7
vi Contents
mdlSetInputPortWidth . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-31
mdlSetOutputPortComplexSignal . . . . . . . . . . . . . . . . . . . . . . 9-32
mdlSetOutputPortDataType . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-33
mdlSetOutputPortDimensionInfo . . . . . . . . . . . . . . . . . . . . . . . 9-34
mdlSetOutputPortSampleTime . . . . . . . . . . . . . . . . . . . . . . . . . 9-36
mdlSetOutputPortWidth . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-37
mdlSetWorkWidths . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-38
mdlStart . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-39
mdlTerminate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-40
mdlUpdate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-41
mdlZeroCrossings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-42
SimStruct Functions
10
Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-2
Language Support . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-2
The SimStruct . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-2
vii
ssGetContStateAddress . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-20
ssGetContStates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-21
ssGetDataTypeName . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-22
ssGetDataTypeId . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-23
ssGetDataTypeSize . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-24
ssGetDataTypeZero . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-25
ssGetDiscStates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-26
ssGetDTypeIdFromMxArray . . . . . . . . . . . . . . . . . . . . . . . . . . 10-27
ssGetDWork . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-29
ssGetDWorkComplexSignal . . . . . . . . . . . . . . . . . . . . . . . . . . 10-30
ssGetDWorkDataType . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-31
ssGetDWorkName . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-32
ssGetDWorkUsedAsDState . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-33
ssGetDWorkWidth . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-34
ssGetdX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-35
ssGetErrorStatus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-36
ssGetInputPortBufferDstPort . . . . . . . . . . . . . . . . . . . . . . . . . 10-37
ssGetInputPortConnected . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-38
ssGetInputPortComplexSignal . . . . . . . . . . . . . . . . . . . . . . . . 10-39
ssGetInputPortDataType . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-40
ssGetInputPortDimensionInfo . . . . . . . . . . . . . . . . . . . . . . . . 10-41
ssGetInputPortDimensions . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-42
ssGetInputPortDirectFeedThrough . . . . . . . . . . . . . . . . . . . . 10-43
ssGetInputPortFrameData . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-44
ssGetInputPortNumDimensions . . . . . . . . . . . . . . . . . . . . . . . 10-45
ssGetInputPortOffsetTime . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-46
ssGetInputPortOverWritable . . . . . . . . . . . . . . . . . . . . . . . . . 10-47
ssGetInputPortRealSignal . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-48
ssGetInputPortRealSignalPtrs . . . . . . . . . . . . . . . . . . . . . . . . 10-49
ssGetInputPortRequiredContiguous . . . . . . . . . . . . . . . . . . . . 10-50
ssGetInputPortReusable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-51
ssGetInputPortSampleTime . . . . . . . . . . . . . . . . . . . . . . . . . . 10-52
ssGetInputPortSampleTimeIndex . . . . . . . . . . . . . . . . . . . . . 10-53
ssGetInputPortSignal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-54
ssGetInputPortSignalAddress . . . . . . . . . . . . . . . . . . . . . . . . . 10-56
ssGetInputPortSignalPtrs . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-57
ssGetInputPortWidth . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-58
ssGetIWork . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-59
ssGetModelName . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-60
ssGetModeVector . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-61
viii Contents
ssGetModeVectorValue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-62
ssGetNonsampledZCs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-63
ssGetNumContStates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-64
ssGetNumDataTypes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-65
ssGetNumDiscStates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-66
ssGetNumDWork . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-67
ssGetNumInputPorts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-68
ssGetNumIWork . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-69
ssGetNumModes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-70
ssGetNumNonsampledZCs . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-71
ssGetNumOutputPorts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-72
ssGetNumParameters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-73
ssGetNumRunTimeParams . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-74
ssGetNumPWork . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-75
ssGetNumRWork . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-76
ssGetNumSampleTimes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-77
ssGetNumSFcnParams . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-78
ssGetOutputPortBeingMerged . . . . . . . . . . . . . . . . . . . . . . . . 10-79
ssGetOutputPortComplexSignal . . . . . . . . . . . . . . . . . . . . . . . 10-80
ssGetOutputPortDataType . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-81
ssGetOutputPortDimensions . . . . . . . . . . . . . . . . . . . . . . . . . 10-82
ssGetOutputPortFrameData . . . . . . . . . . . . . . . . . . . . . . . . . . 10-83
ssGetOutputPortNumDimensions . . . . . . . . . . . . . . . . . . . . . 10-84
ssGetOutputPortOffsetTime . . . . . . . . . . . . . . . . . . . . . . . . . . 10-85
ssGetOutputPortRealSignal . . . . . . . . . . . . . . . . . . . . . . . . . . 10-86
ssGetOutputPortReusable . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-87
ssGetOutputPortSampleTime . . . . . . . . . . . . . . . . . . . . . . . . . 10-88
ssGetOutputPortSignal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-89
ssGetOutputPortSignalAddress . . . . . . . . . . . . . . . . . . . . . . . 10-90
ssGetOutputPortWidth . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-91
ssGetPath . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-92
ssGetParentSS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-93
ssGetPlacementGroup . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-94
ssGetPWork . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-95
ssGetRealDiscStates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-96
ssGetRootSS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-97
ssGetRunTimeParamInfo . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-98
ssGetRWork . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-99
ssGetSampleTimeOffset . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-100
ssGetSampleTimePeriod . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-101
ix
ssGetSFcnParam . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-102
ssGetSFcnParamsCount . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-103
ssGetSimMode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-104
ssGetSolverMode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-105
ssGetSolverName . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-106
ssGetStateAbsTol . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-107
ssGetT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-108
ssGetTNext . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-109
ssGetTaskTime . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-110
ssGetTFinal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-111
ssGetTStart . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-112
ssGetUserData . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-113
ssIsContinuousTask . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-114
ssIsFirstInitCond . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-115
ssIsMajorTimeStep . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-116
ssIsMinorTimeStep . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-117
ssIsSampleHit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-118
ssIsSpecialSampleHit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-119
ssIsVariableStepSolver . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-120
ssPrintf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-121
ssRegAllTunableParamsAsRunTimeParams . . . . . . . . . . . . 10-122
ssRegisterDataType . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-123
ssSetBlockReduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-124
ssSetCallSystemOutput . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-125
ssSetDataTypeSize . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-126
ssSetDataTypeZero . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-127
ssSetDWorkComplexSignal . . . . . . . . . . . . . . . . . . . . . . . . . . 10-129
ssSetDWorkDataType . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-130
ssSetDWorkName . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-131
ssSetDWorkUsedAsDState . . . . . . . . . . . . . . . . . . . . . . . . . . 10-132
ssSetDWorkWidth . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-133
ssSetErrorStatus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-134
ssSetExternalModeFcn . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-135
ssSetInputPortComplexSignal . . . . . . . . . . . . . . . . . . . . . . . 10-136
ssSetInputPortDataType . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-137
ssSetInputPortDimensionInfo . . . . . . . . . . . . . . . . . . . . . . . . 10-138
ssSetInputPortFrameData . . . . . . . . . . . . . . . . . . . . . . . . . . 10-140
ssSetInputPortDirectFeedThrough . . . . . . . . . . . . . . . . . . . . 10-141
ssSetInputPortMatrixDimensions . . . . . . . . . . . . . . . . . . . . 10-142
ssSetInputPortOffsetTime . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-143
x Contents
ssSetInputPortOverWritable . . . . . . . . . . . . . . . . . . . . . . . . . 10-144
ssSetInputPortReusable . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-145
ssSetInputPortRequiredContiguous . . . . . . . . . . . . . . . . . . . 10-147
ssSetInputPortSampleTime . . . . . . . . . . . . . . . . . . . . . . . . . 10-148
ssSetInputPortSampleTimeIndex . . . . . . . . . . . . . . . . . . . . . 10-149
ssSetInputPortVectorDimension . . . . . . . . . . . . . . . . . . . . . . 10-150
ssSetInputPortWidth . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-151
ssSetModeVectorValue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-152
ssSetNumContStates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-153
ssSetNumDiscStates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-154
ssSetNumDWork . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-155
ssSetNumInputPorts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-156
ssSetNumIWork . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-157
ssSetNumModes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-158
ssSetNumNonsampledZCs . . . . . . . . . . . . . . . . . . . . . . . . . . 10-159
ssSetNumOutputPorts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-160
ssSetNumPWork . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-161
ssSetNumRunTimeParams . . . . . . . . . . . . . . . . . . . . . . . . . . 10-162
ssSetNumRWork . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-163
ssSetNumSampleTimes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-164
ssSetNumSFcnParams . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-165
ssSetOffsetTime . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-166
ssSetOptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-167
ssSetOutputPortComplexSignal . . . . . . . . . . . . . . . . . . . . . . 10-171
ssSetOutputPortDataType . . . . . . . . . . . . . . . . . . . . . . . . . . 10-172
ssSetOutputPortDimensionInfo . . . . . . . . . . . . . . . . . . . . . . 10-173
ssSetOutputPortFrameData . . . . . . . . . . . . . . . . . . . . . . . . . 10-174
ssSetOutputPortMatrixDimensions . . . . . . . . . . . . . . . . . . . 10-175
ssSetOutputPortOffsetTime . . . . . . . . . . . . . . . . . . . . . . . . . 10-176
ssSetOutputPortReusable . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-177
ssSetOutputPortSampleTime . . . . . . . . . . . . . . . . . . . . . . . . 10-178
ssSetOutputPortVectorDimension . . . . . . . . . . . . . . . . . . . . 10-179
ssSetOutputPortWidth . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-180
ssSetParameterName . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-181
ssSetParameterTunable . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-182
ssSetPlacementGroup . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-183
ssSetRunTimeParamInfo . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-184
ssSetSampleTime . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-187
ssSetSFcnParamNotTunable . . . . . . . . . . . . . . . . . . . . . . . . 10-188
ssSetSFcnParamTunable . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-189
xi
ssSetSolverNeedsReset . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-190
ssSetStopRequested . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-192
ssSetTNext . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-193
ssSetUserData . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-194
ssSetVectorMode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-195
ssUpdateAllTunableParamsAsRunTimeParams . . . . . . . . . 10-196
ssUpdateRunTimeParamData . . . . . . . . . . . . . . . . . . . . . . . 10-197
ssUpdateRunTimeParamInfo . . . . . . . . . . . . . . . . . . . . . . . . 10-198
ssWarning . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-199
ssWriteRTWMxVectParam . . . . . . . . . . . . . . . . . . . . . . . . . . 10-200
ssWriteRTWMx2dMatParam . . . . . . . . . . . . . . . . . . . . . . . . 10-201
ssWriteRTWParameters . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-202
ssWriteRTWParamSettings . . . . . . . . . . . . . . . . . . . . . . . . . 10-206
ssWriteRTWScalarParam . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-210
ssWriteRTWStr . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-211
ssWriteRTWStrParam . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-212
ssWriteRTWStrVectParam . . . . . . . . . . . . . . . . . . . . . . . . . . 10-213
ssWriteRTWVectParam . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-214
ssWriteRTWWorkVect . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-215
ssWriteRTW2dMatParam . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-216
xii Contents
1
Overview of S-Functions
Introduction . . . . . . . . . . . . . . . . . . . . 1-2
What Is an S-Function? . . . . . . . . . . . . . . . . 1-2
Using S-Functions in Models . . . . . . . . . . . . . . 1-2
Passing Parameters to S-Functions . . . . . . . . . . . 1-3
When to Use an S-Function . . . . . . . . . . . . . . 1-5
How S-Functions Work . . . . . . . . . . . . . . . . 1-5
Implementing S-Functions . . . . . . . . . . . . . . . 1-9
S-Function Concepts . . . . . . . . . . . . . . . . 1-11
S-Function Examples . . . . . . . . . . . . . . . . 1-16
1 Overview of S-Functions
Introduction
S-functions (system-functions) provide a powerful mechanism for extending
the capabilities of Simulink®. The introductory sections of this chapter describe
what an S-function is and when and why you might use one. This chapter then
presents a comprehensive description of how to write your own S-functions.
S-functions allow you to add your own blocks to Simulink models. You can
create your blocks in MATLAB®, C, C++, Fortran, or Ada. By following a set of
simple rules, you can implement your algorithms in an S-function. After you
have written your S-function and placed its name in an S-Function block
(available in the Functions & Tables block library), you can customize the user
interface by using masking.
S-functions can be used with the Real-Time Workshop. You can also customize
the code generated by the Real Time Workshop® for S-functions by writing a
Target Language CompilerTM (TLC) file. See the Target Language Compiler
Reference Guide and the Real-Time Workshop User’s Guide for more
information.
What Is an S-Function?
An S-function is a computer language description of a Simulink block.
S-functions can be written in MATLAB, C, C++, Ada, or Fortran. C, C++, Ada,
and Fortran S-functions are compiled as MEX-files using the mex utility
described in the Application Program Interface Guide. As with other MEX-files,
they are dynamically linked into MATLAB when needed.
S-functions use a special calling syntax that enables you to interact with
Simulink’s equation solvers. This interaction is very similar to the interaction
that takes place between the solvers and built-in Simulink blocks. The form of
an S-function is very general and can accommodate continuous, discrete, and
hybrid systems.
1-2
Introduction
S-function
source file
function[sys
% mysfun M-file
%
switch(flag)
.
.
.
M-file
Figure 1-1: The Relationship Between an S-Function Block, Its Dialog Box,
and the Source File That Defines the Block’s Behavior
In this example, the model contains two instances of an S-Function block. Both
blocks reference the same source file (mysfun, which can be either a C MEX-file
or an M-file). If both a C MEX-file and an M-file exist with the same name, the
C MEX-file takes precedence and is the file that the S-function uses.
1-3
1 Overview of S-Functions
1-4
Introduction
You can use Simulink’s masking facility to create custom dialog boxes and
icons for your S-function blocks. Masked dialog boxes can make it easier to
specify additional parameters for S-functions. For discussions of additional
parameters and masking, see Using Simulink.
An advantage of using S-functions is that you can build a general purpose block
that you can use many times in a model, varying parameters with each
instance of the block.
u x y
(input) (states) (output)
1-5
1 Overview of S-Functions
y = f 0 ( t, x, u ) (output)
x· c = f d ( t, x, u ) (derivative)
x d k + 1 = f u ( t, x, u ) (update)
where x = xc + xd
Simulation Stages
Execution of a Simulink model proceeds in stages. First comes the
initialization phase. In this phase, Simulink incorporates library blocks into
the model, propagates widths, data types, and sample times, evaluates block
parameters, determines block execution order, and allocates memory. Then
Simulink enters a simulation loop, where each pass through the loop is referred
to as a simulation step. During each simulation step, Simulink executes each
of the model’s blocks in the order determined during initialization. For each
block, Simulink invokes functions that compute the block’s states, derivatives,
and outputs for the current sample time. This continues until the simulation is
complete.
1-6
Introduction
Initialize model
Calculate outputs
Clean up at final
time step.
Calculate derivatives
Calculate derivatives
Calculate outputs
Integration
(minor time step)
Calculate derivatives
1-7
1 Overview of S-Functions
1-8
Introduction
Implementing S-Functions
You can implement an S-function as either an M-file or a MEX file. The
following sections describes these alternative implementations and discusses
the advantages of each.
M-file S-Functions
An M-file S-function consists of a MATLAB function of the following form
[sys,x0,str,ts]=f(t,x,u,flag,p1,p2,...)
where f is the S-function’s name, t is the current time, x is the state vector of
the corresponding S-function block, u is the block’s inputs, flag indicates a task
to be performed, and p1, p2, ... are the block’s parameters. During simulation
of a model, Simulink repeatedly invokes f, using flag to indicate the task to be
performed for a particular invocation. Each time the S-function performs the
task, it returns the result in a structure having the format shown in the syntax
example.
A template implementation of an M-file S-function, sfuntmpl.m, resides in
matlabroot/toolbox/simulink/blocks. The template consists of a top-level
function and a set of skeletal subfunctions, each of which corresponds to a
particular value of flag. The top-level function simply invokes the subfunction
indicated by flag. The subfunctions, called S-function callback methods,
perform the actual tasks required of the S-function during simulation. The
following table lists the contents of an M-file S-function that follows this
standard format.
1-9
1 Overview of S-Functions
We recommend that you follow the structure and naming conventions of the
template when creating M-file S-functions. This will make it easier for others
to understand and maintain M-file S-functions that you create. See Chapter 2,
“Writing M S-Functions” for information on creating M-file S-functions.
MEX-file S-Functions
Like an M-file S-function, a MEX-file function consists of a set of callback
routines that Simulink invokes to perform various block-related tasks during
a simulation. Significant differences exist, however. For one, MEX-file
functions are implemented in a different programming language: C, C++, Ada,
or Fortran. Also, Simulink invokes MEX S-function routines directly instead of
via a flag value as with M-file S-functions. Because Simulink invokes the
functions directly, MEX-file functions must follow standard naming
conventions specified by Simulink.
Other key differences exist. For one, the set of callback functions that MEX
functions can implement is much larger than that can be implemented by
M-file functions. Also, an MEX function has direct access to the internal data
structure, called the SimStruct, that Simulink uses to maintain information
about the S-function. MEX-file functions can also use MATLAB’s MEX-file API
to access the MATLAB workspace directly.
A C MEX-file S-function template, called sfuntmpl_basic.c, resides in the
matlabroot/simulink/src directory. The template contains skeletal
implementations of all the required and optional callback routines that a C
MEX-file S-function can implement. For a more amply commented version of
the template, see sfuntmpl_doc.c in the same directory.
1-10
Introduction
compiled language. M-file S-functions also have easier access to MATLAB and
toolbox functions.
The primary advantage of MEX file functions is versatility. The larger number
of callbacks and access to the SimStruct enable MEX-file functions to
implement functionality not accessible to M-file S-functions. Such functionality
includes the ability to handle data types other than double, complex inputs,
matrix inputs, and so on.
S-Function Concepts
Understanding these key concepts should enable you to build S-functions
correctly:
• Direct feedthrough
• Dynamically sized inputs
• Setting sample times and offsets
Direct Feedthrough
Direct feedthrough means that the output (or the variable sample time for
variable sample time blocks) is controlled directly by the value of an input port.
A good rule of thumb is that an S-function input port has direct feedthrough if:
An example of a system that requires its inputs (i.e., has direct feedthrough) is
the operation y = k × u , where u is the input, k is the gain, and y is the output.
An example of a system that does not require its inputs (i.e., does not have
direct feedthrough) is this simple integration algorithm
Outputs: y = x
Derivative: x· = u
where x is the state, x· is the state derivative with respect to time, u is the input
and y is the output. Note that x· is the variable that Simulink integrates. It is
1-11
1 Overview of S-Functions
very important to set the direct feedthrough flag correctly because it affects the
execution order of the blocks in your model and is used to detect algebraic loops.
1-12
Introduction
• Continuous sample time — For S-functions that have continuous states and/
or nonsampled zero crossings (see “How Simulink Works” in Using Simulink
for explanation of zero crossings). For this type of S-function, the output
changes in minor time steps.
• Continuous but fixed in minor time step sample time — For S-functions that
need to execute at every major simulation step, but do not change value
during minor time steps.
• Discrete sample time — If your S-Function block’s behavior is a function of
discrete time intervals, you can define a sample time to control when
Simulink calls the block. You can also define an offset that delays each
sample time hit. The value of the offset cannot exceed the corresponding
sample time.
A sample time hit occurs at time values determined by this formula
TimeHit = (n * period) + offset
1-13
1 Overview of S-Functions
specify that the block’s sample time is inherited. A simple example of this is
a Gain block that inherits its sample time from the block driving it.
where
CONTINUOUS_SAMPLE_TIME = 0.0
FIXED_IN_MINOR_STEP_OFFSET = 1.0
VARIABLE_SAMPLE_TIME = -2.0
or
[INHERITED_SAMPLE_TIME, FIXED_IN_MINOR_STEP_OFFSET]
where
INHERITED_SAMPLE_TIME = -1.0
1-14
Introduction
and
0.0 ≤ offset < discrete_sample_period
The Scope block is a good example of this type of block. This block should run
at the rate, either continuous or discrete, of its driving block, but should
never run in minor step. If it did, the scope display would show the
intermediate computations of the solver rather than the final result at each
time point.
1-15
1 Overview of S-Functions
S-Function Examples
Simulink comes with a library of S-function examples.
To run an example:
It may be helpful to examine some sample S-functions as you read the next
chapters. Code for the examples are stored in these subdirectories under the
MATLAB root directory:
• M-files: toolbox/simulink/blocks
• C, C++, and Fortran: simulink/src
• Ada: simulink/ada/examples
1-16
Introduction
Filename Description
1-17
1 Overview of S-Functions
Filename Description
C S-Function Examples
The simulink/src directory also contains examples of C MEX S-functions,
many of which have an M-file S-function counterpart. These C MEX
S-functions are listed in this table.
Filename Description
1-18
Introduction
Filename Description
sfun_cplx.c Complex signal add with one input port and one
parameter.
sfun_directlook.c Direct 1-D lookup.
sfun_dtype_io.c Example of the use of Simulink data types for
inputs and outputs.
sfun_dtype_param.c Example of the use of Simulink data types for
parameters.
sfun_dynsize.c A simple example of how to size outputs of an
S-function dynamically.
sfun_errhdl.c A simple example of how to check parameters
using the mdlCheckParams S-function routine.
1-19
1 Overview of S-Functions
Filename Description
1-20
Introduction
Filename Description
1-21
1 Overview of S-Functions
Filename Description
Filename Description
Filename Description
1-22
Introduction
1-23
1 Overview of S-Functions
1-24
2
Writing M S-Functions
Introduction . . . . . . . . . . . . . . . . . . . . 2-2
S-Function Arguments . . . . . . . . . . . . . . . . 2-2
S-Function Outputs . . . . . . . . . . . . . . . . . 2-3
Defining S-Function Block Characteristics . . . . . . . . 2-4
Processing S-Function Parameters . . . . . . . . . . . 2-5
A Simple M-File S-Function Example . . . . . . . . . . 2-5
Introduction
An M-file S-function consists of a MATLAB function of the following form
[sys,x0,str,ts]=f(t,x,u,flag,p1,p2,...)
S-Function Arguments
Simulink passes the following arguments to an S-function:
2-2
Introduction
The following table describes the values that flag can assume and lists the
corresponding S-function method for each value.
S-Function Outputs
An M-file returns an output vector containing the following elements:
• sys, a generic return argument. The values returned depend on the flag
value. For example, for flag = 3, sys contains the S-function outputs.
• x0, the initial state values (an empty vector if there are no states in the
system). x0 is ignored, except when flag = 0.
2-3
2 Writing M S-Functions
• str, reserved for future use. M-file S-functions must set this to the empty
matrix, [].
• ts, a two column matrix containing the sample times and offsets of the block.
Continuous systems have their sample time set to zero. The hybrid example,
which starts on page 2-13, demonstrates an S-function with multiple sample
times.
This function returns an uninitialized sizes structure. You must load the
sizes structure with information about the S-function. The table below lists
the sizes structure fields and describes the information contained in each
field.
2-4
Introduction
This passes the information in the sizes structure to sys, a vector that holds
the information for use by Simulink.
2-5
2 Writing M S-Functions
case 0
[sys,x0,str,ts] = mdlInitializeSizes; % Initialization
case 3
sys = mdlOutputs(t,x,u); % Calculate outputs
case { 1, 2, 4, 9 }
sys = []; % Unused flags
otherwise
error(['Unhandled flag = ',num2str(flag)]); % Error handling
end;
% End of function timestwo.
2-6
Introduction
%
ts = [-1 0]; % Inherited sample time
% End of mdlInitializeSizes.
%==============================================================
% Function mdlOutputs performs the calculations.
%==============================================================
function sys = mdlOutputs(t,x,u)
sys = 2*u;
% End of mdlOutputs.
To test this S-function in Simulink, connect a sine wave generator to the input
of an S-Function block. Connect the output of the S-Function block to a Scope.
Double-click on the S-Function block to open the dialog box.
2-7
2 Writing M S-Functions
• Continuous
• Discrete
• Hybrid
• Variable-step
All examples are based on the M-file S-function template found in sfuntmpl.m.
2-8
Examples of M-File S-Functions
case 0
[sys,x0,str,ts]=mdlInitializeSizes(A,B,C,D); % Initialization
case 1
sys = mdlDerivatives(t,x,u,A,B,C,D); % Calculate derivatives
case 3
sys = mdlOutputs(t,x,u,A,B,C,D); % Calculate outputs
2-9
2 Writing M S-Functions
%
str = [];
%
% Initialize the array of sample times; in this example the sample
% time is continuous, so set ts to 0 and its offset to 0.
%
ts = [0 0];
% End of mdlInitializeSizes.
%
%==============================================================
% mdlDerivatives
% Return the derivatives for the continuous states.
%==============================================================
function sys = mdlDerivatives(t,x,u,A,B,C,D)
sys = A*x + B*u;
% End of mdlDerivatives.
%
%==============================================================
% mdlOutputs
% Return the block outputs.
%==============================================================
%
function sys = mdlOutputs(t,x,u,A,B,C,D)
sys = C*x + D*u;
% End of mdlOutputs.
The above example conforms to the simulation stages discussed earlier in this
chapter. Unlike timestwo.m, this example invokes mdlDerivatives to
calculate the derivatives of the continuous state variables when flag = 1. The
system state equations are of the form
x'= Ax + Bu
y = Cx + Du
2-10
Examples of M-File S-Functions
last call to this routine. The memory allocated to the derivative vector changes
during execution.
switch flag,
case 0
sys = mdlInitializeSizes(A,B,C,D); % Initialization
case 2
sys = mdlUpdate(t,x,u,A,B,C,D); % Update discrete states
case 3
sys = mdlOutputs(t,x,u,A,B,C,D); % Calculate outputs
2-11
2 Writing M S-Functions
otherwise
error(['unhandled flag = ',num2str(flag)]); % Error handling
end
% End of dsfunc.
%==============================================================
% Initialization
%==============================================================
sizes = simsizes;
sizes.NumContStates = 0;
sizes.NumDiscStates = 2;
sizes.NumOutputs = 2;
sizes.NumInputs = 2;
sizes.DirFeedthrough = 1; % Matrix D is non-empty.
sizes.NumSampleTimes = 1;
sys = simsizes(sizes);
x0 = ones(2,1); % Initialize the discrete states.
str = []; % Set str to an empty matrix.
ts = [1 0]; % sample time: [period, offset]
% End of mdlInitializeSizes.
%==============================================================
% Update the discrete states
%==============================================================
function sys = mdlUpdates(t,x,u,A,B,C,D)
sys = A*x + B*u;
% End of mdlUpdate.
%==============================================================
% Calculate outputs
%==============================================================
function sys = mdlOutputs(t,x,u,A,B,C,D)
sys = C*x + D*u;
2-12
Examples of M-File S-Functions
% End of mdlOutputs.
2-13
2 Writing M S-Functions
switch flag,
case 0 % Initialization
[sys,x0,str,ts] = mdlInitializeSizes(dperiod,doffset);
case 1
sys = mdlDerivatives(t,x,u); % Calculate derivatives
case 2
sys = mdlUpdate(t,x,u,dperiod,doffset); % Update disc states
case 3
sys = mdlOutputs(t,x,u,doffset,dperiod); % Calculate outputs
case {4, 9}
sys = []; % Unused flags
otherwise
error(['unhandled flag = ',num2str(flag)]); % Error handling
end
% End of mixedm.
%
%==============================================================
% mdlInitializeSizes
% Return the sizes, initial conditions, and sample times for the
% S-function.
%==============================================================
function [sys,x0,str,ts] = mdlInitializeSizes(dperiod,doffset)
sizes = simsizes;
sizes.NumContStates = 1;
sizes.NumDiscStates = 1;
sizes.NumOutputs = 1;
sizes.NumInputs = 1;
sizes.DirFeedthrough = 0;
sizes.NumSampleTimes = 2;
sys = simsizes(sizes);
x0 = ones(2,1);
str = [];
ts = [0, 0 % sample time
dperiod, doffset];
% End of mdlInitializeSizes.
2-14
Examples of M-File S-Functions
%==============================================================
% mdlDerivatives
% Compute derivatives for continuous states.
%==============================================================
%
function sys = mdlDerivatives(t,x,u)
sys = u;
% end of mdlDerivatives.
%
%==============================================================
% mdlUpdate
% Handle discrete state updates, sample time hits, and major time
% step requirements.
%==============================================================
%
function sys = mdlUpdate(t,x,u,dperiod,doffset)
% Next discrete state is output of the integrator.
% Return next discrete state if we have a sample hit within a
% tolerance of 1e-8. If we don't have a sample hit, return [] to
% indicate that the discrete state shouldn't change.
%
if abs(round((t-doffset)/dperiod)-(t-doffset)/dperiod) < 1e-8
sys = x(1); % mdlUpdate is "latching" the value of the
% continuous state, x(1), thus introducing a delay.
else
sys = []; % This is not a sample hit, so return an empty
end % matrix to indicate that the states have not
% changed.
% End of mdlUpdate.
%
%==============================================================
% mdlOutputs
% Return the output vector for the S-function.
%==============================================================
%
function sys = mdlOutputs(t,x,u,doffset,dperiod)
% Return output of the unit delay if we have a
% sample hit within a tolerance of 1e-8. If we
2-15
2 Writing M S-Functions
else
sys = []; % This is not a sample hit, so return an empty
end % matrix to indicate that the output has not changed
% End of mdlOutputs.
case 0
[sys,x0,str,ts] = mdlInitializeSizes; % Initialization
case 2
sys = mdlUpdate(t,x,u); % Update Discrete states
case 3
sys = mdlOutputs(t,x,u); % Calculate outputs
2-16
Examples of M-File S-Functions
case 4
sys = mdlGetTimeOfNextVarHit(t,x,u); % Get next sample time
case { 1, 9 }
sys = []; % Unused flags
otherwise
error(['Unhandled flag = ',num2str(flag)]); % Error handling
end
% End of vsfunc.
%==============================================================
% mdlInitializeSizes
% Return the sizes, initial conditions, and sample times for the
% S-function.
%==============================================================
%
function [sys,x0,str,ts] = mdlInitializeSizes
%
% Call simsizes for a sizes structure, fill it in and convert it
% to a sizes array.
%
sizes = simsizes;
sizes.NumContStates = 0;
sizes.NumDiscStates = 1;
sizes.NumOutputs = 1;
sizes.NumInputs = 2;
sizes.DirFeedthrough = 1; % flag=4 requires direct feedthrough
% if input u is involved in
% calculating the next sample time
% hit.
sizes.NumSampleTimes = 1;
sys = simsizes(sizes);
%
% Initialize the initial conditions.
%
x0 = [0];
%
% Set str to an empty matrix.
%
str = [];
%
2-17
2 Writing M S-Functions
mdlGetTimeOfNextVarHit returns the “time of the next hit,” the time in the
simulation when vsfunc is next called. This means that there is no output from
this S-function until the time of the next hit. In vsfunc, the time of the next hit
is set to t + u(2), which means that the second input, u(2), sets the time when
the next call to vsfunc occurs.
2-18
3
Writing S-Functions in C
Introduction . . . . . . . . . . . . . . . . . . . . 3-2
Creating C MEX S-Functions . . . . . . . . . . . . . . 3-3
Introduction
A C MEX-file that defines an S-Function block must provide information about
the model to Simulink during the simulation. As the simulation proceeds,
Simulink, the ODE solver, and the MEX-file interact to perform specific tasks.
These tasks include defining initial conditions and block characteristics, and
computing derivatives, discrete states, and outputs.
As with M-file S-functions, Simulink interacts with a C MEX-file S-function by
invoking callback methods that the S-function implements. Each method
performs a predefined task, such as computing block outputs, required to
simulate the block whose functionality the S-function defines. Simulink
defines in a general way the task of each callback. The S-function is free to
perform the task according to the functionality it implements. For example,
Simulink specifies that the S-function’s mdlOutput method must compute that
block’s outputs at the current simulation time. It does not specify what those
outputs must be. This callback-based API allows you to create S-functions, and
hence custom blocks, of any desired functionality.
The set of callback methods, hence functionality, that C MEX-files can
implement is much larger than that available for M-file S-functions. See
Chapter 9, “S-Function Callback Methods” for descriptions of the callback
methods that a C MEX-file S-function can implement. Unlike M-file
S-functions, C MEX-files can access and modify the data structure that
Simulink uses internally to store information about the S-function. The ability
to implement a broader set of callback methods and to access internal data
structures allows C-MEX files to implement a wider set of block features, such
as the ability to handle matrix signals and multiple data types.
C MEX-file S-functions are required to implement only a small subset of the
callback methods that Simulink defines. If your block does not implement a
particular feature, such as matrix signals, you are free to omit the callback
methods required to implement a feature. This allows you to create simple
blocks very quickly.
The general format of a C MEX S-function is shown below.
#define S_FUNCTION_NAME your_sfunction_name_here
#define S_FUNCTION_LEVEL 2
#include "simstruc.h"
3-2
Introduction
{
}
Note Unlike M-file S-functions, C MEX S-function methods do not each have
a flag parameter. This is because Simulink calls each S-function method
directly at the appropriate time during the simulation.
3-3
3 Writing S-Functions in C
3-4
Using the S-Function Builder
1 Set the MATLAB current directory to the directory in which you want to
create the S-function.
3-5
3 Writing S-Functions in C
6 If the S-function has parameters, enter default values for the parameters in
the S-function parameters field.
7 Use the specification and code entry panes on the S-Function Builder
dialog box to enter information and custom source code required to tailor the
generated S-function to your application (see “Customizing the S-Function”
on page 3-8).
8 If you have not already done so, configure the MATLAB mex command to
work on your system.
To configure the mex command, type mex -setup at the MATLAB command
line.
3-6
Using the S-Function Builder
Simulink builds a MEX file that implements the specified S-function and
saves the file in the current directory (“How the S-Function Builder Builds
an S-Function” on page 3-7).
After generating the S-function source code, the S-Function Builder uses the
MATLAB mex command to build the MEX file representation the S-function
from the generated source code and any external custom source code and
libraries that you specified.
3-7
3 Writing S-Functions in C
Initialization Pane
The Initialization pane allows you to specify basic features of the S-function,
such as the width of its input and output ports and its sample time.
The S-Function Builder uses the information that you enter on this pane to
generate the S-function’s mdlInitializeSizes callback method. Simulink
invokes this method during the model initialization phase of the simulation to
obtain basic information about the S-function. (see “How Simulink Interacts
with C S-Functions” on page 3-32 for more information on the model
initialization phase).
3-8
Using the S-Function Builder
Input port width. Width of the S-function’s input port. The width is the number
of elements that a vector signal connected to the port must have. To permit
connection of matrix (2-D) signals to the input port, specify -1 as the input port
width.
Output port width. Width of the S-function’s output port. The width is the
number of elements in the vector that this S-function outputs. If the S-function
outputs matrix signals, specify -1 as the port width.
Sample time. Sample time of the S-function. The sample time is the length of the
interval between the times when the S-function updates its output. You can
select one of the following options:
• Inherited
The S-function inherits its sample time from the block connected to its input
port.
• Continuous
The block updates its outputs at each simulation step.
• Discrete
The S-function updates its outputs at the rate specified in the Discrete
sample time value field of the S-Function Builder dialog box.
Discrete sample time value. Interval between updates of the S-function’s outputs.
This field is enabled only if you have selected Discrete as the S-function’s
Sample time.
Number of discrete states. Number of discrete states that the S-function has.
Discrete states IC. Initial conditions of the S-function’s discrete states. You can
enter the values as a comma-separated list or as a vector (e.g., [0 1 2]). The
number of initial conditions must equal the number of discrete states.
Number of continuous states. Number of continuous states that the S-function has.
3-9
3 Writing S-Functions in C
Continuous states IC. Initial conditions of the S-function’s continuous states. You
can enter the values as a comma-separated list or as a vector (e.g., [0 1 2]).
The number of initial conditions must equal the number of continuos states.
Libraries Pane
The Libraries pane allows you to specify the location of external code files
referenced by custom code that you enter in other panes of the S-Function
Builder dialog box.
3-10
Using the S-Function Builder
3-11
3 Writing S-Functions in C
Outputs Pane
Use the Outputs pane to enter code that computes the outputs of the
S-function at each simulation time step.
3-12
Using the S-Function Builder
Code for the mdlOutputs function. Code that computes the output of the S-function
at each simulation time step (or sample time hit in the case of a discrete
S-function.) When generating the source code for the S-function, the
S-Function Builder inserts the code in this field in a wrapper function of the
form
void sfun_Outputs_wrapper(const real_T *u,
real_T *y,
const real_T *xD, /* optional */
const real_T *xC, /* optional */
const real_T *param0, /* optional */
int_T p_width0 /* optional */
real_T *param1 /* optional */
int_t p_width1 /* optional */
int_T y_width, /* optional */
int_T u_width) /* optional */
{
where sfun is the name of the S-function. The S-Function Builder inserts a call
to this wrapper function in the mdlOutputs callback method that it generates
for your S-function. Simulink invokes the mdlOutputs method at each
simulation time step (or sample time step in the case of a discrete S-function)
to compute the S-function’s output. The S-function’s mdlOutputs method in
turn invokes the wrapper function containing your output code. Your output
code then actually computes and returns the S-function’s output.
3-13
3 Writing S-Functions in C
The mdlOutputs method passes some or all of the following arguments to the
outputs wrapper function.
Argument Description
3-14
Using the S-Function Builder
Argument Description
These arguments permit you to compute the output of the block as a function
of its inputs and, optionally, its states and parameters. The code that you enter
in this field can invoke external functions declared in the header files or
external declarations on the Libraries pane. This allows you to use existing
code to compute the outputs of the S-function.
Inputs are needed in the output function. Checked if the current values of the
S-function’s inputs are used to compute its outputs. Simulink uses this
information to detect algebraic loops created by directly or indirectly
connecting the S-function’s output to its input.
3-15
3 Writing S-Functions in C
3-16
Using the S-Function Builder
where sfun is the name of the S-function. The S-Function Builder inserts a call
to this wrapper function in the mdlDerivatives callback method that it
generates for the S-function. Simulink calls the mdlDerivatives method at the
end of each time step to obtain the derivatives of the S-function’s continuous
states (see “How Simulink Interacts with C S-Functions” on page 3-32).
Simulink’s solver numerically integrates the derivatives to determine the
continuous states at the next time step. At the next time step, Simulink passes
the updated states back to the S-function’s mdlOutputs method (see “Outputs
Pane” on page 3-12).
The generated S-function’s mdlDerivatives callback method passes the
following arguments to the derivatives wrapper function:
•u
•y
• dx
• xC
• param0, p_width0, param1, p_width1, ... paramN, p_widthN
• y_width
• x-width
3-17
3 Writing S-Functions in C
Enter code to compute the values s of the S-function’s discrete states in the
Code for the mdlUpdate function field on this pane. When generating code,
the S-Function Builder takes the code in this pane and inserts it in a wrapper
function of the form
void sfun_Update_wrapper(const real_T *u,
const real_T *y,
real_T *xD,
const real_T *param0, /* optional */
int_T p_width0, /* optional */
real_T *param1,/* optional */
int_T p_width1, /* optional */
int_T y_width, /* optional */
int_T u_width) /* optional */
3-18
Using the S-Function Builder
where sfun is the name of the S-function. The S-Function Builder inserts a call
to this wrapper function in the mdlUpdate callback method that it generates for
the S-function. Simulink calls the mdlUpdate method at the end of each time
step to obtain the values of the S-function’s discrete states at the next time step
(see “How Simulink Interacts with C S-Functions” on page 3-32). At the next
time step, Simulink passes the updated states back to the S-function’s
mdlOutputs method (see “Outputs Pane” on page 3-12).
See “mdlOutputs” on page 3-25 for the meanings and usage of these
arguments. Your code should use the xD (discrete states) variable to return the
values of the derivatives that it computes. The arguments allow your code to
compute the discrete states as functions of the S-function’s inputs, outputs,
and, optionally, parameters. Your code can invoke external functions declared
on the Libraries pane.
3-19
3 Writing S-Functions in C
Show compile steps. Log each build step in the Compilation diagnostics field.
Generate wrapper TLC. Generate a TCL file. You do not need to generate a TLC
file if you do not expect the S-function ever to run in accelerated mode or be
used in a model from which RTW generates code.
Save code only. Do not build a MEX file from the generated source code.
3-20
Using the S-Function Builder
3-21
3 Writing S-Functions in C
The following model uses the timestwo S-function to double the amplitude of a
sine wave and plot it in a scope.
The block dialog for the S-function specifies timestwo as the S-function name;
the parameters field is empty.
The timestwo S-function contains the S-function callback methods shown in
this figure.
Start of simulation
mdlInitializeSizes
Initialization
mdlInitializeSampleTimes
mdlOutputs
Simulation
loop
mdlTerminate
3-22
Example of a Basic C MEX S-Function
#include “simstruc.h”
if (!ssSetNumOutputPorts(S,1)) return;
ssSetOutputPortWidth(S, 0, DYNAMICALLY_SIZED);
ssSetNumSampleTimes(S, 1);
3-23
3 Writing S-Functions in C
The first specifies the name of the S-function (timestwo). The second specifies
that the S-function is in the level 2 format (for more information about level 1
and level 2 S-functions, see “Converting Level 1 C MEX S-Functions to Level
2” on page 3-41).
After defining these two items, the example includes simstruc.h, which is a
header file that gives access to the SimStruct data structure and the MATLAB
Application Program Interface (API) functions.
#define S_FUNCTION_NAME timestwo
#define S_FUNCTION_LEVEL 2
#include "simstruc.h"
The simstruc.h file defines a a data structure, called the SimStruct, that
Simulink uses to maintain information about the S-function. The simstruc.h
file also defines macros that enable your MEX-file to set values in and get
values (such as the input and output signal to the block) from the SimStruct
(see Chapter 10, “SimStruct Functions”).
Callback Implementations
The next part of the timestwo S-function contains implementations of callback
methods required by Simulink.
3-24
Example of a Basic C MEX S-Function
mdlInitializeSizes
Simulink calls mdlInitializeSizes to inquire about the number of input and
output ports sizes of the ports and any other objects (such as the number of
states) needed by the S-function.
The timestwo implementation of mdlInitializeSizes specifies the following
size information:
• Zero parameters
This means that the S-function parameters field of the S-functions’s dialog
box must be empty. If it contains any parameters, Simulink will report a
parameter mismatch.
• One input port and one output port
The widths of the input and output ports are dynamically sized. This tells
Simulink to multiply each element of the input signal to the S-function by
two and to place the result in the output signal. Note that the default
handling for dynamically sized S-functions for this case (one input and one
output) is that the input and output widths are equal.
• One sample time
The timestwo example specifies the actual value of the sample time in the
mdlInitializeSampleTimes routine.
• The code is exception free.
mdlInitializeSampleTimes
Simulink calls mdlInitializeSampleTimes to set the sample time(s) of the
S-function. A timestwo block executes whenever the driving block executes.
Therefore, it has a single inherited sample time, SAMPLE_TIME_INHERITED.
mdlOutputs
Simulink calls mdlOutputs at each time step to calculate a block’s outputs. The
timestwo implementation of mdlOutputs takes the input, multiplies it by two,
and writes the answer to the output.
3-25
3 Writing S-Functions in C
to access the input signal. The macro returns a vector of pointers, which must
be accessed using
*uPtrs[i]
to get the width of the signal passing through the block. Finally the S-function
loops over the inputs to compute the outputs.
mdlTerminate
Perform tasks at end of simulation. This is a mandatory S-function routine.
However, the timestwo S-function doesn’t need to perform any termination
actions, so this routine is empty.
3-26
Example of a Basic C MEX S-Function
mex timestwo.c
at the command line. The mex command compiles and links the timestwo.c file
to create a dynamically loadable executable for Simulink’s use.
The resulting executable is referred to as a MEX S-function, where MEX
stands for “MATLAB EXecutable.” The MEX-file extension varies from
platform to platform. For example, in Microsoft Windows, the MEX-file
extension is .dll.
3-27
3 Writing S-Functions in C
Note We recommend that you use the C MEX-file template when developing
MEX S-functions.
3-28
Templates for C S-Functions
Note All S-functions from Simulink 1.3 through 2.1 are considered to be level
1 S-functions. They are compatible with Simulink 3.0, but we recommend that
you write new S-functions in the level 2 format.
When compiling your S-function for use with the Real-Time Workshop,
simstruc.h includes the following.
3-29
3 Writing S-Functions in C
#else
#include "cg_sfun.h" /* Code generation registration func */
#endif
These statements select the appropriate code for your particular application:
Note This trailer code must not be in the body of any S-function routine.
The SimStruct
The file matlabroot/simulink/include/simstruc.h is a C language header
file that defines the Simulink data structure and the SimStruct access macros.
It encapsulates all the data relating to the model or S-function, including block
parameters and outputs.
There is one SimStruct data structure allocated for the Simulink model. Each
S-function in the model has its own SimStruct associated with it. The
organization of these SimStructs is much like a directory tree. The SimStruct
associated with the model is the root SimStruct. The SimStructs associated
with the S-functions are the child SimStructs.
Note By convention, port indices begin at 0 and finish at the total number of
ports minus 1.
Simulink provides a set of macros that S-functions can use to access the fields
of the SimStruct. See Chapter 10, “SimStruct Functions” for more information.
3-30
Templates for C S-Functions
Compiling C S-Functions
S-functions can be compiled in one of three modes identified by the presence of
one of the following defines:
3-31
3 Writing S-Functions in C
Process View
The following figures shows the order in which Simulink invokes an
S-function’s callback methods.
3-32
How Simulink Interacts with C S-Functions
Model Initialization
mdlIntializeSizes mdlCheckParameters
mdlSetInputPortFrameData
mdlSetInputPortWidth/mdlSetOutputPortWidth
mdlSetInputPortDimensionInfo/mdlSetOutputPortDimensionInfo
mdlSetInputPortSampleTime/mdlSetOutputPortSampleTime
Simulink Engine
mdlInitializeSampleTime
mdlSetInputPortDataType/mdlSetOutputPortDatatype
mdlSetDefaultPortDataTypes
mdlSetInputPortComplexSignal/mdlSetOutputPortComplexSignal
mdlSetDefaultPortComplexSignals
mdlInitializeConditions
Sets output of
mdlOutputs
constant blocks
To simulation loop
3-33
3 Writing S-Functions in C
Simulation Loop
Initialize Model
mdlGetTimeOfNextVarHit
mdlOutputs
Simulink Engine
mdlUpdate
mdlCheckParameters
mdlOutputs
minor time step
mdlDerivatives
mdlZeroCrossings
mdlTerminate
End Simulation
3-34
How Simulink Interacts with C S-Functions
Model Initialization
parameter change loop
mdlCheckParameters p. 9-3
External mode
mdlProcessParameters p. 9-18
mdlTerminate p. 9-40
Simulink calls mdlRTW once when it enters external mode and again each time
a parameter changes or when you select Update Diagram under your model’s
Edit menu.
3-35
3 Writing S-Functions in C
Data View
S-function blocks have input and output signals, parameters, internal states,
plus other general work areas. In general, block inputs and outputs are written
to, and read from, a block I/O vector. Inputs can also come from
Block outputs can also go to the external outputs via the root outport blocks. In
addition to input and output signals, S-functions can have:
• Continuous states
• Discrete states
• Other working areas such as real, integer or pointer work vectors
External External
Inputs Outputs
Block I/O (root
(root
inport outport
blocks) blocks)
Ground Block
Work
Vectors,
DWork,
RWork,
States Parameters IWork,
PWork,
...
3-36
How Simulink Interacts with C S-Functions
• Via pointers
• Using contiguous inputs
This is an array of pointers, where portIndex starts at 0. There is one for each
input port. To access an element of this signal you must use
*uPtrs[element]
Input 1 S-function
Input 2 Block
To Access Input 1:
InputRealPtrsType uPtrs0 = ssGetInputPortRealSignalPtrs(S,0)
uPtrs0
...
To Access Input 2:
InputRealPtrsType uPtrs1 = ssGetInputPortRealSignalPtrs(S,1)
uPtrs1
...
...
Block I/O
Vector
3-37
3 Writing S-Functions in C
Note that input array pointers may point at noncontiguous places in memory.
You can retrieve the output signal by using this code.
real_T *y = ssGetOutputPortSignal(S,outputPortIndex);
A common mistake is to try and access the input signals via pointer arithmetic.
For example, if you were to place
real_T *u = *uPtrs; /* Incorrect */
just below the initialization of uPtrs and replace the inner part of the above
loop with
*y++ = *u++; /* Incorrect */
the code compiles, but the MEX-file may crash Simulink. This is because it is
possible to access invalid memory (which depends on how you build your
model). When accessing the input signals incorrectly, a crash will happen when
the signals entering your S-function block are not contiguous. Noncontiguous
signal data occur when signals pass through virtual connection blocks such as
the Mux or Selector blocks.
3-38
How Simulink Interacts with C S-Functions
To verify that you are correctly accessing wide input signals, pass a replicated
signal to each input port of your S-function. This is done by creating a Mux
block with the number of input ports equal to the width of the desired signal
entering your S-function. Then the driving source should be connected to each
input port as shown in this figure.
3-39
3 Writing S-Functions in C
3-40
Converting Level 1 C MEX S-Functions to Level 2
3-41
3 Writing S-Functions in C
- For mixed continuous and discrete state S-functions, the state vector no
longer consists of the continuous states followed by the discrete states. The
states are saved in separate vectors and hence may not be contiguous in
memory.
• The mdlOutputs prototype has changed from
static void mdlOutputs( real_T *y, const real_T *x,
const real_T *u, SimStruct *S, int_T tid)
to:
static void mdlOutputs(SimStruct *S, int_T tid)
Since y, x, and u are not explicitly passed into Level-2 S-functions, you must
use:
- ssGetInputPortSignal to access inputs.
- ssGetOutputPortSignal to access the outputs.
- ssGetContStates or ssGetRealDiscStates to access the states.
• The mdlUpdate function prototype has been changed from
void mdlUpdate(real_T *x, real_T *u, Simstruct *S, int_T tid)
to:
void mdlUpdate(SimStruct *S, int_T tid)
3-42
Converting Level 1 C MEX S-Functions to Level 2
• Replace all obsolete SimStruct macros. See “Obsolete Macros” on page 3–43
for a complete list of obsolete macros.
• When converting level 1 S-functions to level 2 S-functions, you should build
your S-functions with full (i.e., highest) warning levels. For example, if you
have gcc on a UNIX system, use these options with the mex utility.
mex CC=gcc CFLAGS=-Wall sfcn.c
On a PC, to use the highest warning levels, you must create a project file
inside of the integrated development environment (IDE) for the compiler you
are using. Within the project file, define MATLAB_MEX_FILE and add
matlabroot/simulink/include
matlabroot/extern/include
Obsolete Macros
The following macros are obsolete. Each obsolete macro should be replaced
with the specified macro.
ssGetY(S) ssGetOutputPortRealSignal(S,port)
3-43
3 Writing S-Functions in C
ssGetSampleTimeEvent(S,sti) ssGetSampleTime(S,sti)
ssSetSampleTimeEvent(S,t) ssSetSampleTime(S,sti,t)
ssGetOffsetTimeEvent(S,sti) ssGetOffsetTime(S,sti)
ssSetOffsetTimeEvent(S,sti,t) ssSetOffsetTime(S,sti,t)
ssIsSampleHitEvent(S,sti,tid) ssIsSampleHit(S,sti,tid)
ssGetNumInputArgs(S) ssGetNumSFcnParams(S)
ssGetNumArgs(S) ssGetSFcnParamsCount(S)
ssGetArg(S,argNum) ssGetSFcnParam(S,argNum)
3-44
4
Overview
The procedure for creating C++ S-functions is nearly the same as that for
creating C S-functions (see Chapter 3, “Writing S-Functions in C”). This section
explains the differences.
4-2
Source File Format
#include "iostream.h"
class counter {
double x;
public:
counter() {
x = 0.0;
}
double output(void) {
x = x + 1.0;
return x;
}
};
#ifdef __cplusplus
extern "C" { // use the C fcn-call standard for all functions
#endif // defined within this scope
#define S_FUNCTION_LEVEL 2
#define S_FUNCTION_NAME sfun_counter_cpp
/*
* Need to include simstruc.h for the definition of the SimStruct and
* its associated macro definitions.
4-3
4 Creating C++ S-Functions
*/
#include "simstruc.h"
/*====================*
* S-function methods *
*====================*/
ssSetNumContStates(S, 0);
ssSetNumDiscStates(S, 0);
ssSetNumSampleTimes(S, 1);
ssSetNumRWork(S, 0);
ssSetNumIWork(S, 0);
ssSetNumPWork(S, 1); // reserve element in the pointers vector
ssSetNumModes(S, 0); // to store a C++ object
ssSetNumNonsampledZCs(S, 0);
ssSetOptions(S, 0);
}
4-4
Source File Format
/*=============================*
* Required S-function trailer *
*=============================*/
4-5
4 Creating C++ S-Functions
#ifdef __cplusplus
} // end of extern "C" scope
#endif
4-6
Making C++ Objects Persistent
2 Store a pointer to each object that you want to be persistent in the pointer
work vector.
static void mdlStart(SimStruct *S)
{
ssGetPWork(S)[0] = (void *) new counter; // store new C++ object in the
} // pointers vector
4-7
4 Creating C++ S-Functions
Note The extension of the source file for a C++ S-function must be .cpp to
ensure that the compiler treats the file’s contents as C++ code.
4-8
5
Introduction
Simulink allows you to use the Ada programming language to create
S-functions. As with S-functions coded in other programming languages,
Simulink interacts with an Ada S-function by invoking callback methods that
the S-function implements. Each method performs a predefined task, such as
computing block outputs, required to simulate the block whose functionality
the S-function defines. Creating an Ada S-function thus entails writing Ada
implementations of the callback methods required to simulate the S-function
and then compiling and linking the callbacks into a library that Simulink can
load and invoke during simulation The following sections explain how to
perform theses tasks.
5-2
Ada S-Function Source File Format
The specification should also specify each callback method that the S-function
implements as an Ada procedure exported to C. The following is an example
of an Ada S-function specification that meets these requirements.
-- The Simulink API for Ada S-Function
with Simulink; use Simulink;
package Times_Two is
end Times_Two;
5-3
5 Creating Ada S-Functions
begin
-- Set the input port attributes
--
ssSetNumInputPorts( S, 1);
ssSetInputPortWidth( S, 0, DYNAMICALLY_SIZED);
ssSetInputPortDataType( S, 0, SS_DOUBLE);
ssSetInputPortDirectFeedThrough(S, 0, TRUE);
ssSetInputPortOverWritable( S, 0, FALSE);
ssSetInputPortOptimizationLevel(S, 0, 3);
exception
when E : others =>
if ssGetErrorStatus(S) = "" then
ssSetErrorStatus(S,
"Exception occured in mdlInitializeSizes. " &
"Name: " & Exception_Name(E) & ", " &
"Message: " & Exception_Message(E) &
" and " & "Information: " &
Exception_Information(E));
end if;
end mdlInitializeSizes;
5-4
Ada S-Function Source File Format
begin
if uWidth = 1 then
for Idx in 0 .. yWidth-1 loop
Y(Idx) := 2.0 * U(0);
end loop;
else
for Idx in 0 .. yWidth-1 loop
Y(Idx) := 2.0 * U(Idx);
end loop;
end if;
exception
when E : others =>
if ssGetErrorStatus(S) = "" then
ssSetErrorStatus(S,
"Exception occured in mdlOutputs. " &
"Name: " & Exception_Name(E) & ", " &
"Message: " & Exception_Message(E) & " and " &
"Information: " & Exception_Information(E));
end if;
end mdlOutputs;
end Times_Two;
5-5
5 Creating Ada S-Functions
5-6
Writing Callback Methods in Ada
Note When interacting with Ada S-functions, Simulink invokes only a subset
of the callback methods that it invokes for C S-functions. The “Languages
Supported” section of the reference page for each callback method specifies
whether Simulink invokes that callback when interacting with an Ada
S-function.
Implementing Callbacks
Simulink defines in a general way the task of each callback. The S-function is
free to perform the task according to the functionality it implements. For
example, Simulink specifies that the S-function’s mdlOutput method must
compute that block’s outputs at the current simulation time. It does not specify
what those outputs must be. This callback-based API allows you to create
S-functions, and hence custom blocks, that meet your requirements.
Chapter 9, “S-Function Callback Methods” explains the purpose of each
callbacks and provides guidelines for implementing them. Chapter 3, “Writing
S-Functions in C” provides information on using these callbacks to implement
specific S-function features, such as the ability to handle multiple signal data
types.
SimStruct Functions
Simulink provides a set of functions that enable an Ada S-function to access the
internal data structure (SimStruct) that Simulink maintains for the
S-function. These functions consist of Ada wrappers around the SimStruct
macros used to access the SimStruct from a C S-function (see Chapter 10,
“SimStruct Functions”). Simulink provides Ada wrappers for a substantial
5-7
5 Creating Ada S-Functions
5-8
Building an Ada S-Function
Note To build a MEX file from Ada source code, using the mex tool, you must
have previously installed a copy of version 3.2 (or higher) of the GNAT Ada95
compiler on your system. You can obtain the latest Solaris, Windows, and
GNU-Linux versions of the compiler at the GNAT ftp site (ftp://
cs.nyu.edu/pub/gnat). Make sure that the compiler executable is in
MATLAB’s command path so that the mex tool can find it.
5-9
5 Creating Ada S-Functions
5-10
Example of an Ada S-Function
The following model uses the timestwo S-function to double the amplitude of a
sine wave and plot it in a scope.
The block dialog for the S-function specifies timestwo as the S-function name;
the parameters field is empty.
The timestwo S-function contains the S-function callback methods shown in
this figure.
Start of simulation
mdlInitializeSizes
Initialization
mdlInitializeSampleTimes
mdlOutputs
Simulation
loop
end of simulation
5-11
5 Creating Ada S-Functions
The source code for the timestwo S-function comprises two parts:
• Package specification
• Package body
package Times_Two is
end Times_Two;
The package specification begins by specifying that the S-function uses the
Simulink package.
with Simulink; use Simulink;
The Simulink package defines Ada procedures for accessing the internal data
structure (SimStruct) that Simulink maintains for each S-function (see
Chapter 10, “SimStruct Functions”).
5-12
Example of an Ada S-Function
The name ada_times_two serves to distinguish the MEX file generated from
Ada source from those generated from the timestwo source coded in other
languages.
Finally the specification specifies the callback methods implemented by the
timestwo S-function.
procedure mdlInitializeSizes(S : in SimStruct);
pragma Export(C, mdlInitializeSizes, "mdlInitializeSizes");
The specification specifies that the Ada compiler should compile each method
as a C-callable function. This is because the Simulink engine assumes that
callback methods are C functions.
Note When building an Ada S-function, MATLAB’s mex tool uses the package
specification to determine which callbacks the S-function does not implement.
It then generates stubs for the non implemented methods.
begin
-- Set the input port attributes
--
ssSetNumInputPorts( S, 1);
5-13
5 Creating Ada S-Functions
ssSetInputPortWidth( S, 0, DYNAMICALLY_SIZED);
ssSetInputPortDataType( S, 0, SS_DOUBLE);
ssSetInputPortDirectFeedThrough(S, 0, TRUE);
ssSetInputPortOverWritable( S, 0, FALSE);
ssSetInputPortOptimizationLevel(S, 0, 3);
exception
when E : others =>
if ssGetErrorStatus(S) = "" then
ssSetErrorStatus(S,
"Exception occured in mdlInitializeSizes. " &
"Name: " & Exception_Name(E) & ", " &
"Message: " & Exception_Message(E) & " and " &
"Information: " & Exception_Information(E));
end if;
end mdlInitializeSizes;
begin
if uWidth = 1 then
for Idx in 0 .. yWidth-1 loop
Y(Idx) := 2.0 * U(0);
end loop;
else
for Idx in 0 .. yWidth-1 loop
Y(Idx) := 2.0 * U(Idx);
end loop;
end if;
5-14
Example of an Ada S-Function
exception
when E : others =>
if ssGetErrorStatus(S) = "" then
ssSetErrorStatus(S,
"Exception occured in mdlOutputs. " &
"Name: " & Exception_Name(E) & ", " &
"Message: " & Exception_Message(E) & " and " &
"Information: " & Exception_Information(E));
end if;
end mdlOutputs;
end Times_Two;
mdlInitializeSizes
Simulink calls mdlInitializeSizes to inquire about the number of input and
output ports sizes of the ports and any other objects (such as the number of
states) needed by the S-function.
The timestwo implementation of mdlInitializeSizes uses SimStruct
functions defined in the Simulink package to specify the following size
information:
Finally the method provides an exception handler to handle any errors that
occur in invoking the SimStruct functions.
mdlOutputs
Simulink calls mdlOutputs at each time step to calculate a block’s outputs. The
timestwo implementation of mdlOutputs takes the input, multiplies it by two,
and writes the answer to the output.
5-15
5 Creating Ada S-Functions
Finally the method loops over the inputs to compute the outputs.
5-16
6
Creating Fortran
S-Functions
Introduction . . . . . . . . . . . . . . . . . . . . 6-2
Level 1 Versus Level 2 S-Functions . . . . . . . . . . . 6-2
Introduction
There are two main strategies to executing Fortran code from Simulink. One is
from a Level 1 Fortran-MEX (F-MEX) S-function, the other is from a Level 2
gateway S-function written in C. Each has its advantages and both can be
incorporated into code generated by the Real-Time Workshop.
6-2
Creating Level 1 Fortran S-Functions
3 Compile the edited file into a MEX file, using the mex command.
4 Include the MEX file in your model, using the S-Function block.
Example
The example file, matlabroot/simulink/src/sfun_timestwo_for.for,
implements an S-function that multiplies its input by two.
C
C File: SFUN_TIMESTWO_FOR.F
C
C Abstract:
C A sample Level 1 FORTRAN representation of a
C timestwo S-function.
C
C The basic mex command for this example is:
C
C >> mex sfun_timestwo_for.for simulink.for
C
C Copyright 1990-2000 The MathWorks, Inc.
C
C $Revision: 1.1 $
C
C=====================================================
C Function: SIZES
C
C Abstract:
C Set the size vector.
C
C SIZES returns a vector which determines model
C characteristics. This vector contains the
C sizes of the state vector and other
C parameters. More precisely,
6-3
6 Creating Fortran S-Functions
SIZE(1) = 0
SIZE(2) = 0
SIZE(3) = 1
SIZE(4) = 1
SIZE(5) = 0
SIZE(6) = 1
RETURN
END
C
C=====================================================
C
C Function: OUTPUT
C
C Abstract:
C Perform output calculations for continuous
C signals.
C
C=====================================================
C .. Parameters ..
SUBROUTINE OUTPUT(T, X, U, Y)
REAL*8 T
REAL*8 X(*), U(*), Y(*)
RETURN
END
C
C=====================================================
C
C Stubs for unused functions.
6-4
Creating Level 1 Fortran S-Functions
C
C=====================================================
SUBROUTINE INITCOND(X0)
REAL*8 X0(*)
C --- Nothing to do.
RETURN
END
SUBROUTINE DOUTPUT(T, X, U, Y)
REAL*8 T, X(*), U(*), Y(*)
C --- Nothing to do.
RETURN
END
6-5
6 Creating Fortran S-Functions
6-6
Creating Level 2 Fortran S-Functions
Template File
The file matlabroot/simulink/src/sfungate.c is a C-MEX template file for
calling into a Fortran subroutine. It will work with a simple Fortran
subroutine, if you modify the Fortran subroutine name in the code.
Mex Environment
Remember that mex -setup needs to find both the C and the Fortran compilers.
If you install or change compilers it is necessary to run mex -setup after
installation or reconfiguration of compilers.
Test out the installation and setup using sample MEX files from MATLAB's C
and Fortran MEX examples in matlabroot/extern/examples/mex as well as
Simulink's examples, which are located in matlabroot/simulink/src.
Compiler Compatibility
Your C and Fortran compilers need to use the same object format. If you use
the compilers explicitly supported by the mex command this is not a problem.
When using the C gateway to Fortran, it is possible to use Fortran compilers
not supported by the mex command, but only if the object file format is
compatible with the C compiler format. Common object formats include ELF
and COFF.
6-7
6 Creating Fortran S-Functions
The compiler must also be configurable so that the caller cleans up the stack
instead of the callee. Compaq Visual Fortran (formerly known as Digital
Fortran) is one compiler whose default stack cleanup is the callee.
Symbol Decorations
Symbol decorations can cause runtime errors. For example, g77 will decorate
subroutine names with a trailing underscore when in its default configuration.
You can either recognize this and adjust the C function prototype or alter the
Fortran compiler’s name decoration policy via command line switches, if the
compiler supports this. See the Fortran compiler manual about altering symbol
decoration policies.
If all else fails, use utilities, such as od (octal dump), to display the symbol
names. For example, the command
od -s 2 <file>
on Linux.
0000115 EÈÙ
0000136 EÈÙ
0000271 EȺ
0000467 ÇEÈ@
0000530 ÇEÈ
0000575 EÈÙEäØ5@
0001267 Cf¦VC-ò:C
0001323 :|.-:8Æ#8ýKw6
0001353 ?333@
0001364 333À
0001414 01.01
0001425 GCC: (GNU) egcs-2.91.66 19990314/Linux
0001522 .symtab
0001532 .strtab
0001542 .shstrtab
0001554 .text
0001562 .rel.text
0001574 .data
0001602 .bss
6-8
Creating Level 2 Fortran S-Functions
0001607 .note
0001615 .comment
0003071 sfun_atmos_for.for
0003101 gcc2_compiled.
0003120 rearth.0
0003131 gmr.1
0003137 htab.2
0003146 ttab.3
0003155 ptab.4
0003164 gtab.5
0003173 atmos_
0003207 exp
0003213 pow_d
Note that Atmos has been changed to atmos_ and the latter is what the C
program must call to be successful.
With Compaq Visual Fortran, the symbol is suppressed, so that Atmos becomes
ATMOS (no underscore).
Note On UNIX, the -lf2c option follows the conventional UNIX library
linking syntax where ’-l’ is the library option itself and ’f2c’ is the unique
part of the library file’s name, libf2c.a. Be sure to use the -L option for the
library search path since -I is only followed while searching for include files.
The f2c package can be obtained for Windows and UNIX environments from
the Internet. The file libf2c.a is usually part of g77 distributions, or else the
file is not needed as the symbols match. In obscure cases, it must be installed
separately, but even this is not difficult once the need for it is identified.
6-9
6 Creating Fortran S-Functions
On Windows using Microsoft Visual C/C++ and Compaq Visual Fortran 6.0
(formerly known as Digital Fortran), this example can be compiled using the
following mex commands (each command is on one line).
mex -v COMPFLAGS#”$COMPFLAGS /iface:cref” -c sfun_atmos_sub.for
-f ..\..\bin\win32\mexopts\df60opts.bat
mex -v LINKFLAGS#”$LINKFLAGS dfor.lib dfconsol.lib dfport.lib
/LIBPATH:$DF_ROOT\DF98\LIB” sfun_atmos.c sfun_atmos_sub.obj
CFortran
Or try using CFortran to create an interface. CFortran is a tool for automated
interface generation between C and Fortran modules, in either direction.
Search the Web for cfortran or visit
http://www-zeus.desy.de/~burow/cfortran/
for downloading.
6-10
Creating Level 2 Fortran S-Functions
Simple Case
The Fortran code must at least be callable in a “step at a time” fashion. If the
code doesn’t have any states, it can be called from mdlOutputs() and no
mdlDerivatives() or mdlUpdate() methods are required.
Setup Code
If there is a lengthy setup calculation, it is best to make this part of the code
separable from the “one step at a time” code and call it from mdlStart(). This
can either be a separate SUBROUTINE called from mdlStart() that
communicates with the rest of the code through COMMON blocks or argument
I/O, or it can be part of the same piece of Fortran code that is isolated by an
IF-THEN-ELSE construct. This construct can be triggered by one of the input
arguments that tells the code if it is to either perform the setup calculations or
the “one step” calculations.
6-11
6 Creating Fortran S-Functions
2 Identify variables that need to be inputs and outputs and put them in the
It is customary to strip out all hard-coded cases and output dumps. In the
Simulink environment, you want to convert inputs and outputs into block
I/O.
Arguments to a SUBROUTINE
Most Fortran compilers generate SUBROUTINE code that passes arguments “by
reference.” This means that the C code calling the Fortran code must use only
pointers in the argument list.
PROGRAM ...
becomes
SUBROUTINE somename( U, X, Y )
A SUBROUTINE never has a return value. I/O is achieved by using some of the
arguments for input, the rest for output.
6-12
Creating Level 2 Fortran S-Functions
Arguments to a FUNCTION
A FUNCTION has a scalar return value passed by value, so a calling C program
should expect this. The argument list is passed by reference (i.e., pointers) as
in the SUBROUTINE.
If the result of a calculation is an array, then a subroutine should be used as a
FUNCTION cannot return an array.
On some UNIX systems where the C and Fortran compiler were installed
separately (or aren’t aware of each other), you may need to reference the library
libf2c.a. To do this, use the -lf2c flag.
UNIX only: if the libf2c.a library isn’t on the library path, you need to add it
the path to the mex process explicitly with the -L command, for instance:
mex -L/usr/local/lib/ -lf2c sfun_atmos.c sfun_atmos_sub.o
6-13
6 Creating Fortran S-Functions
This sample is prebuilt and is on the MATLAB search path already, so you can
see it working by opening the sample model sfcndemo_atmos.mdl. Just type
sfcndemo_atmos
at the command prompt, or to get all the S-function demos for Simulink, type
sfcndemos at the MATLAB prompt.
6-14
Porting Legacy Code
Sample Times
Be sure if the code has an implicit step size in its algorithm, coefficients, etc.,
that you register the proper discrete sample time in the
mdlInitializeSampleTimes() S-function method and only change the block's
output values from the mdlUpdate() method.
Multiple Instances
If you plan on having multiple copies of this S-function used in one Simulink
model, it is necessary to allocate storage for each copy of the S-function in the
model. The recommended approach is to use DWork vectors, see matlabroot/
6-15
6 Creating Fortran S-Functions
6-16
7
Implementing
Block Features
Introduction . . . . . . . . . . . . . . . . . . . . 7-2
Introduction
This chapter explains how to use S-function callback methods to implement
various block features.
7-2
Dialog Parameters
Dialog Parameters
A user can pass parameters to an S-function at the start of and, optionally,
during the simulation, using the S-Function parameters field of the block’s
dialog box. Such parameters are called dialog box parameters to distinguish
them from run-time parameters created by the S-function to facilitate code
generation (see “Run-Time Parameters” on page 7-6). Simulink stores the
values of the dialog box parameters in the S-function’s SimStruct structure.
Simulink provides callback methods and SimStruct macros that allow the
S-function to access and check the parameters and use them in the
computation of the block’s output.
If you want your S-function to be able to use dialog parameters, you must
perform the following steps when you create the S-function:
Specify S as the first argument and the relative position of the parameter in
the list entered on the dialog box (0 is the first position) as the second
argument. The ssGetSFcnParam returns a pointer to the mxArray containing
the parameter. You can use ssGetDTypeIdFromMxArray to get the data type
of the parameter.
When running a simulation, the user must specify the parameters in the
S-Function parameters field of the block’s dialog box in the same order that
you defined them in step 1 above. The user can enter any valid MATLAB
expression as the value of a parameter, including literal values, names of
workspace variables, function invocations, or arithmetic expressions. Simulink
evaluates the expression and passes its value to the S-function.
7-3
7 Implementing Block Features
For example, the following code is part of a device driver S-function. Four input
parameters are used: BASE_ADDRESS_PRM, GAIN_RANGE_PRM, PROG_GAIN_PRM,
and NUM_OF_CHANNELS_PRM. The code uses #define statements to associate
particular input arguments with the parameter names.
/* Input Parameters */
#define BASE_ADDRESS_PRM(S) ssGetSFcnParam(S, 0)
#define GAIN_RANGE_PRM(S) ssGetSFcnParam(S, 1)
#define PROG_GAIN_PRM(S) ssGetSFcnParam(S, 2)
#define NUM_OF_CHANNELS_PRM(S) ssGetSFcnParam(S, 3)
When running the simulation, a user would enter four variable names or
values in the S-Function parameters field of the block’s dialog box. The first
corresponds to the first expected parameter, BASE_ADDRESS_PRM(S). The
second corresponds to the next expected parameter, and so on.
The mdlInitializeSizes function contains this statement.
ssSetNumSFcnParams(S, 4);
Tunable Parameters
Dialog parameters can be either tunable or nontunable. A tunable parameter
is a parameter that a user can change while the simulation is running. Use the
macro ssSetSFcnParamTunable in mdlInitializeSizes to specify the
tunability of each dialog parameter used by the macro.
7-4
Dialog Parameters
7-5
7 Implementing Block Features
Run-Time Parameters
Simulink allows an S-function to create and use internal representations of
external dialog parameters called run-time parameters. Every run-time
parameter corresponds to one or more dialog parameters and can have the
same value and data type as its corresponding external parameter(s) or a
different value or data type. If a run-time parameter differs in value or data
type from its external counterpart, the dialog parameter is said to have been
transformed to create the run-time parameter. The value of a run-time
parameter that corresponds to multiple dialog parameter is typically a function
of the values of the dialog parameters. Simulink allocates and frees storage for
run-time parameters and provides functions for updating and accessing them,
thus eliminating the need for S-functions to performs these tasks.
Run-time parameters facilitate the following kinds of S-function operations:
• Computed parameters
Often the output of a block is a function of the values of several dialog
parameters. For example, suppose a block has two parameters, the volume
and density of some object, and the output of the block is a function of the
input signal and the weight of the object. In this case, the weight can be
viewed as a third internal parameter computed from the two external
parameters, volume and density. An S-function can create a run-time
parameter corresponding to the computed weight, thereby eliminating the
need to provide special case handling for weight in the output computation.
• Data type conversions
Often a block may need to change the data type of a dialog parameter to
facilitate internal processing. For example, suppose that the output of the
block is a function of the input and a parameter and the input and parameter
are of different data types. In this case, the S-function can create a run-time
parameter that has the same value as the dialog parameter but has the data
type of the input signal and use the run-time parameter in the computation
of the output.
• Code generation
During code generation, Real-Time Workshop writes all run-time
parameters automatically to the model.rtw file, eliminating the need for
the S-function to perform this task via a mdlRTW method.
7-6
Run-Time Parameters
7-7
7 Implementing Block Features
7-8
Input and Output Ports
• The dimensions of the input port (see “Initializing Input Port Dimensions”
on page 7-10)
If you want your S-function to inherit its dimensionality from the port to
which it is connected, you should specify that the port is dynamically sized
in mdlInitializeSizes (see “Sizing an Input Port Dynamically” on
page 7-10).
• Whether the input port allows scalar expansion of inputs (see “Scalar
Expansion of Inputs” on page 7-12)
• Whether the input port has direct feedthrough, using
ssSetInputPortDirectFeedThrough
A port has direct feedthrough if the input is used in either the mdlOutputs or
mdlGetTimeOfNextVarHit functions. The direct feedthrough flag for each
input port can be set to either 1=yes or 0=no. It should be set to 1 if the input,
u, is used in the mdlOutput or mdlGetTimeOfNextVarHit routine. Setting the
direct feedthrough flag to 0 tells Simulink that u will not be used in either of
these S-function routines. Violating this will lead to unpredictable results.
• The data type of the input port, if not the default double
Use ssSetInputPortDataType to set the input port’s data type. If you want
the data type of the port to depend on the data type of the port to which it is
connected, specify the data type as DYNAMICALLY_TYPED. In this case, you
must provide implementations of the mdlSetInputPortDataType and
mdlSetDefaultPortDataTypes methods to enable the data type to be set
correctly during signal propagation.
7-9
7 Implementing Block Features
• The numeric type of the input port, if the port accepts complex-valued signals
Use ssSetInputComplexSignal to set the input port’s numeric type. If you
want the numeric type of the port to depend on the numeric type of the port
to which it is connected, specify the data type as inherited. In this case, you
must provide implementations of the mdlSetInputPortComplexSignal and
mdlSetDefaultPortComplexSignal methods to enable the numeric type to
be set correctly during signal propagation.
• If the input signal is one-dimensional, and the input port width is w, use
ssSetInputPortVectorDimension(S, inputPortIdx, w)
• If the input signal is a matrix of dimension m-by-n, use
ssSetInputPortMatrixDimensions(S, inputPortIdx, m, n)
• Otherwise use
ssSetInputPortDimensionInfo(S, inputPortIdx, dimsInfo)
This function can be used to fully or partially initialize the port dimensions
(see next section).
• Specify some or all of the dimensions of the input port as dynamically sized
in mdlInitializeSizes
7-10
Input and Output Ports
7-11
7 Implementing Block Features
If you want the port’s dimensions to depend on block connectivity, set the
dimensions to DYNAMICALLY_SIZED. The S-function must then provide
mdlSetOutputPortDimensionInfo and ssSetDefaultPortDimensionInfo
methods to ensure that output port dimensions are set to the correct values
in code generation.
• Data type of the output port
Use ssSetOutputPortDataType to set the output port’s data type. If you want
the data type of the port to depend on block connectivity, specify the data
type as DYNAMICALLY_TYPED. In this case, you must provide implementations
of the mdlSetOutputPortDataType and mdlSetDefaultPortDataTypes
methods to enable the data type to be set correctly during signal propagation.
• The numeric type of the input port, if the port outputs complex-valued
signals
Use ssSetOutputComplexSignal to set the output port’s numeric type. If you
want the numeric type of the port to depend on the numeric type of the port
to which it is connected, specify the data type as inherited. In this case, you
must provide implementations of the mdlSetOutputPortComplexSignal and
mdlSetDefaultPortComplexSignal methods to enable the numeric type to
be set correctly during signal propagation.
The best way to understand the scalar expansion rules is to consider a sum
block with two input ports, where the first input signal is scalar, the second
input signal is a 1-D vector with w > 1 elements, and the output signal is a 1-D
vector with w elements. In this case, the scalar input is expanded to a 1-D vector
with w elements in the output method, and each element of the expanded signal
is set to the value of the scalar input.
Outputs
<snip>
u1inc = (u1width > 1);
7-12
Input and Output Ports
If the block has more than two inputs, each input signal must be scalar, or the
wide signals must have the same number of elements. In addition, if the wide
inputs are driven by 1-D and 2-D vectors, the output will be a 2-D vector signal,
and the scalar inputs are expanded to a 2-D vector signal.
The way scalar expansion actually works depends on whether the S-function
manages the dimensions of its input and output ports using
mdlSetInputPortWidth and mdlSetOutputPortWidth or
mdlSetInputPortDimensionInfo, mdlSetOutputPortDimensionInfo, and
mdlSetDefaultPortDimensionInfo.
If the S-function does not specify/control the dimensions of its input and output
ports using the above methods, Simulink uses a default method to set the input
and output ports using the above methods, Simulink uses a default method to
set the S-function port dimensions.
In mdlInitializeSizes method, the S-function can enable scalar expansion
for its input ports by setting the SS_OPTION_ALLOW_INPUT_SCALAR_EXPANSION
option, using ssSetOptions. Simulink default method uses the above option to
allow or disallow scalar expansion for a block input ports. If the above option is
not set by an S-function, Simulink assumes all ports (input and output ports)
must have the same dimensions, and it sets all port dimensions to the same
dimensions specified by one of the driving blocks.
If the S-function specifies/controls the dimensions of its input and output ports,
Simulink ignores the SCALAR_EXPANSION option.
See matlabroot/simulink/src/sfun_multiport.c for an example.
7-13
7 Implementing Block Features
set_param('block','MaskSelfModifiable','on')
at the MATLAB prompt before saving the library. Failure to specify that the
mask modifies the appearance of the block means that an instance of the block
in a model reverts to the number of ports in the library whenever you load the
model or update the library link.
7-14
Custom Data Types
3 Specify the value that represents zero for the data type, using
ssSetDataTypeZero.
7-15
7 Implementing Block Features
Sample Times
Simulink supports blocks that execute at different rates. An S-function block
can specify its rates (i.e., sample times) as:
With block-based sample times, the S-function specifies a set of operating rates
for the block as a whole during the initialization phase of the simulation.With
port-based sample times, the S-function specifies a sample time for each input
and output port individually during initialization. During the execution phase,
with block-based sample times, the S-function processes all inputs and outputs
each time a sample hit occurs for the block. By contrast, with port-based
sample times, the block processes a particular port only when a sample hit
occurs for that port.
For example, consider two sample rates, 0.5 and 0.25 seconds, respectively:
• In the block-based method, selecting 0.5 and 0.25 would direct the block to
execute inputs and outputs at 0.25 second increments.
• In the port-based method, you could set the input port to 0.5 and the output
port to 0.25, and the block would process inputs at 2Hz and outputs at 4Hz.
You should use port-based sample times if your application requires unequal
sample rates for input and output execution or if you don’t want the overhead
associated with running input and output ports at the highest sample rate of
your block.
In some applications, an S-Function block may need to operate internally at
one or more sample rates while inputting or outputting signals at other rates.
The hybrid block- and port-based method of specifying sample rates allows you
to create such blocks.
In typical applications, you will specify only one block-based sample time.
Advanced S-functions may require the specification of port-based or multiple
block sample times.
7-16
Sample Times
• mdlInitializeSizes
• mdlInitializeSampleTimes
A third sections presents a simple example that shows how to specify sample
times in mdlInitializeSampleTimes.
where numSampleTimes > 0. This tells Simulink that your S-function has
block-based sample times. Simulink calls mdlInitializeSampleTimes, which
in turn sets the sample times.
7-17
7 Implementing Block Features
[CONTINUOUS_SAMPLE_TIME, 0.0 ]
[CONTINUOUS_SAMPLE_TIME, FIXED_IN_MINOR_STEP_OFFSET]
[discrete_sample_period, offset ]
[VARIABLE_SAMPLE_TIME , 0.0 ]
Alternatively, you can specify that the sample time is inherited from the
driving block in which case the S-function can have only one sample time pair
[INHERITED_SAMPLE_TIME, 0.0 ]
or
[INHERITED_SAMPLE_TIME, FIXED_IN_MINOR_STEP_OFFSET]
where
discrete_sample_period > 0.0
and
0.0 <= offset < discrete_sample_period
If your function has no intrinsic sample time, then you must indicate that it is
inherited according to the following guidelines:
• A function that changes as its input changes, even during minor integration
steps, should register the [INHERITED_SAMPLE_TIME, 0.0] sample time.
7-18
Sample Times
• A function that changes as its input changes, but doesn’t change during
minor integration steps (that is, held during minor steps), should register the
[INHERITED_SAMPLE_TIME, FIXED_IN_MINOR_STEP_OFFSET] sample time.
To check for a sample hit during execution (in mdlOutputs or mdlUpdate), use
the ssIsSampleHit or ssIsContinuousTask macro. For example, if your first
sample time is continuous, then you used the following code fragment to check
for a sample hit. Note that you would get incorrect results if you used
ssIsSampleHit(S,0,tid).
if (ssIsContinuousTask(S,tid)) {
}
If, for example, you wanted to determine if the third (discrete) task has a hit,
then you would use the following code-fragment.
if (ssIsSampleHit(S,2,tid) {
}
Example: mdlInitializeSampleTimes
This example specifies that there are two discrete sample times with periods of
0.01 and 0.5 seconds.
static void mdlInitializeSampleTimes(SimStruct *S)
{
ssSetSampleTime(S, 0, 0.01);
ssSetOffsetTime(S, 0, 0.0);
ssSetSampleTime(S, 1, 0.5);
ssSetOffsetTime(S, 1, 0.0);
} /* End of mdlInitializeSampleTimes. */
7-19
7 Implementing Block Features
with:
ssSetInputPortSampleTime(S, idx, period)
ssSetInputPortOffsetTime(S, idx, offset)
ssSetOutputPortSampleTime(S, idx, period)
ssSetOutputPortOffsetTime(S, idx, offset)
7-20
Sample Times
Finally, as in the port-based method, you specify the rates for each port, using
ssSetInputPortSampleTime(S, idx, period)
ssSetInputPortOffsetTime(S, idx, offset)
ssSetOutputPortSampleTime(S, idx, period)
ssSetOutputPortOffsetTime(S, idx, offset)
Note that each of the assigned port rates must be the same as one of the
previously declared block rates.
where S is the SimStruct, st_index identifies a specific sample time index, and
tid is the task ID (tid is an argument to the mdlOutput and mdlUpdate).
For example, these statements specify three sample times: one for continuous
behavior, and two for discrete behavior.
ssSetSampleTime(S, 0, CONTINUOUS_SAMPLE_TIME);
ssSetSampleTime(S, 1, 0.75);
ssSetSampleTime(S, 2, 1.0);
In the mdlUpdate function, the following statement would encapsulate the code
that defines the behavior for the sample time of 0.75 second.
if (ssIsSampleHit(S, 1, tid)) {
}
The second argument, 1, corresponds to the second sample time, 0.75 second.
7-21
7 Implementing Block Features
ssSetSampleTime(S, 0, CONTINUOUS_SAMPLE_TIME);
ssSetOffsetTime(S, 0, 0.0);
}
In the second sample time, the offset causes Simulink to call the mdlUpdate
function at these times: 0.025 second, 0.125 second, 0.225 second, and so on, in
increments of 0.1 second.
The following statement, which indicates how many sample times are defined,
also appears in the mdlInitializeSizes function.
ssSetNumSampleTimes(S, 2);
7-22
Sample Times
Suppose, for example, that your model has an input port operating at one rate,
0, and an output port operating at a slower rate, 1. Further, suppose that you
want the output port to output the value currently on the input. The following
example illustrates usage of this macro.
if (ssISampleHit(S, 0, tid) {
if (ssIsSpecialSampleHit(S, 0, 1, tid) {
/* Transfer input to output memory. */
...
}
}
if (ssIsSampleHit(S, 1, tid) {
/* Emit output. */
...
}
In this example, the first block runs when a sample hit occurs at the input rate.
If the hit also occurs at the output rate, the block transfers the input to the
output memory. The second block runs when a sample hit occurs at the output
rate. It transfers the output in its memory area to the block’s output.
Note that higher-rate tasks always run before slower-rate tasks. Thus, the
input task in the preceding example always runs before the output task,
ensuring that valid data is always present at the output port.
7-23
7 Implementing Block Features
Work Vectors
If your S-function needs persistent memory storage, use S-function work
vectors instead of static or global variables. If you use static or global variables,
they are used by multiple instances of your S-function. This occurs when you
have multiple S-Function blocks in a Simulink model and the same S-function
C MEX-file has been specified. The ability to keep track of multiple instances
of an S-function is called re-entrancy.
You can create an S-function that is re-entrant by using work vectors. These
are persistent storage locations that Simulink manages for an S-function.
Integer, floating point (real), pointer, and general data types are supported.
The number of elements in each vector can be specified dynamically as a
function of the number of inputs to the S-function.
Work vectors have several advantages:
For example, suppose you’d like to track the previous value of each input signal
element entering input port 1 of your S-function. Either the discrete-state
vector or the real-work vector could be used for this, depending upon whether
the previous value is considered a discrete state (that is, compare the unit delay
and the memory block). If you do not want the previous value to be logged when
states are saved, use the real-work vector, rwork. To do this, in
mdlInitializeSizes specify the length of this vector by using ssSetNumRWork.
Then in either mdlStart or mdlInitializeConditions, initialize the rwork
vector, ssGetRWork. In mdlOutputs, you can retrieve the previous inputs by
using ssGetRWork. In mdlUpdate, update the previous value of the rwork vector
by using ssGetInputPortRealSignalPtrs.
7-24
Work Vectors
Use the macros in this table to specify the length of the work vectors for each
instance of your S-function in mdlInitializeSizes.
Macro Description
• 0 (the default). This indicates that the vector is not used by your S-function.
• A positive nonzero integer. This is the width of the vector that will be
available for use by mdlStart, mdlInitializeConditions, and S-function
routines called in the simulation loop.
• The DYNAMICALLY_SIZED define. The default behavior for dynamically sized
vectors is to set them to the overall block width. Simulink does this after
propagating line widths and sample times. The block width is the width of
the signal passing through your block. In general this is equal to the output
port width.
If the default behavior of dynamically sized vectors does not meet your needs,
use mdlSetWorkWidths and the macros listed in Table 7-1, Macros Used in
Specifying Vector Widths to set explicitly the sizes of the work vectors. Also,
mdlSetWorkWidths allows you to set your work vector lengths as a function of
the block sample time and/or port widths.
7-25
7 Implementing Block Features
The continuous states are used when you have a state that needs to be
integrated by one of Simulink’s solvers. When you specify continuous states,
you must return the states’ derivatives in mdlDerivatives. The discrete state
vector is used to maintain state information that changes at fixed intervals.
Typically the discrete state vector is updated in place in mdlUpdate.
The integer, real and pointer work vectors are storage locations that do not get
logged by Simulink during simulations. They maintain persistent data
between calls to your S-function.
The code below uses the pointer-work vector to store a FILE pointer, returned
from the standard I/O function, fopen.
#define MDL_START /* Change to #undef to remove function. */
#if defined(MDL_START)
static void mdlStart(real_T *x0, SimStruct *S)
7-26
Work Vectors
{
FILE *fPtr;
void **PWork = ssGetPWork(S);
fPtr = fopen("file.data", "r");
PWork[0] = fPtr;
}
#endif /* MDL_START */
This code retrieves the FILE pointer from the pointer-work vector and passes it
to fclose to close the file.
static void mdlTerminate(SimStruct *S)
{
if (ssGetPWork(S) != NULL) {
FILE *fPtr;
fPtr = (FILE *) ssGetPWorkValue(S,0);
if (fPtr != NULL) {
fclose(fPtr);
}
ssSetPWorkValue(S,0,NULL);
}
}
Note If you are using mdlSetWorkWidths, then any work vectors you use in
your S-function should be set to DYNAMICALLY_SIZED in mdlInitializeSizes,
even if the exact value is known before mdlIntializeSizes is called. The size
to be used by the S-function should be specified in mdlSetWorkWidths.
The synopsis is
#define MDL_SET_WORK_WIDTHS /* Change to #undef to remove function. */
#if defined(MDL_SET_WORK_WIDTHS) && defined(MATLAB_MEX_FILE)
static void mdlSetWorkWidths(SimStruct *S)
{
}
#endif /* MDL_SET_WORK_WIDTHS */
7-27
7 Implementing Block Features
Memory Allocation
When creating an S-function, it is possible that the available work vectors don’t
provide enough capability. In this case, you will need to allocate memory for
each instance of your S-function. The standard MATLAB API memory
allocation routines (mxCalloc, mxFree) should not be used with C MEX
S-functions. The reason is that these routines are designed to be used with
MEX-files that are called from MATLAB and not Simulink. The correct
approach for allocating memory is to use the stdlib.h (calloc, free) library
routines. In mdlStart allocate and initialize the memory and place the pointer
to it either in pointer-work vector elements
ssGetPWork(S)[i] = ptr;
7-28
Function-Call Subsystems
Function-Call Subsystems
You can create a triggered subsystem whose execution is determined by logic
internal to an S-function instead of by the value of a signal. A subsystem so
configured is called a function-call subsystem. To implement a function-call
subsystem:
7-29
7 Implementing Block Features
7-30
Handling Errors
Handling Errors
When working with S-functions, it is important to handle unexpected events
correctly such as invalid parameter values.
If your S-function has parameters whose contents you need to validate, use the
following technique to report errors encountered.
ssSetErrorStatus(S,"error encountered due to ...");
return;
7-31
7 Implementing Block Features
If you do not call mexErrMsgTxt or other API routines that cause exceptions,
then use the SS_OPTION_EXCEPTION_FREE_CODE S-function option. This is done
by issuing the following command in the mdlInitializeSizes function.
ssSetOptions(S, SS_OPTION_EXCEPTION_FREE_CODE);
Setting this option will increase the performance of your S-function by allowing
Simulink to bypass the exception handling setup that is usually performed
prior to each S-function invocation. Extreme care must be taken to verify that
your code is exception free when using SS_OPTION_EXCEPTION_FREE_CODE. If
your S-function generates an exception when this option is set, unpredictable
results will occur.
All mex* routines have the potential of long jumping. In addition several mx*
routines have the potential of long jumping. To avoid any difficulties, use only
the API routines that retrieve a pointer or determine the size of parameters.
For example, the following will never throw an exception: mxGetPr, mxGetData,
mxGetNumberOfDimensions, mxGetM, mxGetN, and mxGetNumberOfElements.
Code in run-time routines can also throw exceptions. Run-time routines refer
to certain S-function routines that Simulink calls during the simulation loop
(see “How Simulink Interacts with C S-Functions” on page 3-32). The run-time
routines include:
• mdlGetTimeOfNextVarHit
• mdlOutputs
• mdlUpdate
• mdlDerivatives
If all run-time routines within your S-function are exception free, you can use
this option.
ssSetOptions(S, SS_OPTION_RUNTIME_EXCEPTION_FREE_CODE);
7-32
Handling Errors
To enable array bounds checking, select warning or error from the Bounds
checking options list on the Simulation Parameters dialog box or enter the
following command at the MATLAB command line.
set_param(modelName, 'ArrayBoundsChecking', 'none' | 'warning' |
'error')
7-33
7 Implementing Block Features
S-Function Examples
Most S-Function blocks require the handling of states, continuous or discrete.
The following sections discuss common types of systems that you can model in
Simulink with S-functions:
• Continuous state
• Discrete state
• Hybrid
• Variable step sample time
• Zero crossings
• Time varying continuous transfer function
u xc y
(input) (states) (output)
y = f 0 ( t, x c, u ) (output)
x· c = f d ( t, x c, u ) (derivative)
7-34
S-Function Examples
Next, the example enters the integration section of the flowchart. Here
Simulink performs a number of minor time steps during which it calls
mdlOutputs and mdlDerivatives. Each of these pairs of calls is referred to as
an integration stage. The integration returns with the continuous states
updated and the simulation time moved forward. Time is moved forward as far
as possible, providing that error tolerances in the state are met. The maximum
time step is subject to constraints of discrete events such as the actual
simulation stop time and the user-imposed limit.
Note that csfunc.c specifies that the input port has direct feedthrough. This
is because matrix D is initialized to a nonzero matrix. If D were set equal to a
zero matrix in the state-space representation, the input signal isn’t used in
mdlOutputs. In this case, the direct feedthrough can be set to 0, which indicates
that csfunc.c does not require the input signal when executing mdlOutputs.
matlabroot/simulink/src/csfunc.c
/* File : csfunc.c
* Abstract:
*
* Example C-file S-function for defining a continuous system.
*
* x' = Ax + Bu
* y = Cx + Du
*
* For more details about S-functions, see simulink/src/sfuntmpl_doc.c.
*
* Copyright 1990-2000 The MathWorks, Inc.
* $Revision: 1.7 $
*/
#include "simstruc.h"
7-35
7 Implementing Block Features
/*====================*
* S-function methods *
*====================*/
ssSetNumContStates(S, 2);
ssSetNumDiscStates(S, 0);
ssSetNumSampleTimes(S, 1);
ssSetNumRWork(S, 0);
ssSetNumIWork(S, 0);
ssSetNumPWork(S, 0);
ssSetNumModes(S, 0);
ssSetNumNonsampledZCs(S, 0);
7-36
S-Function Examples
#define MDL_INITIALIZE_CONDITIONS
/* Function: mdlInitializeConditions ========================================
* Abstract:
* Initialize both continuous states to zero.
*/
static void mdlInitializeConditions(SimStruct *S)
{
real_T *x0 = ssGetContStates(S);
int_T lp;
for (lp=0;lp<2;lp++) {
*x0++=0.0;
}
}
/* y=Cx+Du */
y[0]=C[0][0]*x[0]+C[0][1]*x[1]+D[0][0]*U(0)+D[0][1]*U(1);
y[1]=C[1][0]*x[0]+C[1][1]*x[1]+D[1][0]*U(0)+D[1][1]*U(1);
}
#define MDL_DERIVATIVES
/* Function: mdlDerivatives =================================================
* Abstract:
* xdot = Ax + Bu
*/
static void mdlDerivatives(SimStruct *S)
{
real_T *dx = ssGetdX(S);
real_T *x = ssGetContStates(S);
InputRealPtrsType uPtrs = ssGetInputPortRealSignalPtrs(S,0);
/* xdot=Ax+Bu */
dx[0]=A[0][0]*x[0]+A[0][1]*x[1]+B[0][0]*U(0)+B[0][1]*U(1);
dx[1]=A[1][0]*x[0]+A[1][1]*x[1]+B[1][0]*U(0)+B[1][1]*U(1);
7-37
7 Implementing Block Features
u xd y
(input) (states) (output)
y = f 0 ( t, x d, u ) (output)
x d + 1 = f u ( t, x d, u ) (update)
7-38
S-Function Examples
matlabroot/simulink/src/dsfunc.c
/* File : dsfunc.c
* Abstract:
*
* Example C-file S-function for defining a discrete system.
*
* x(n+1) = Ax(n) + Bu(n)
* y(n) = Cx(n) + Du(n)
*
* For more details about S-functions, see simulink/src/sfuntmpl_doc.c.
*
* Copyright 1990-2000 The MathWorks, Inc.
* $Revision: 1.10 $
*/
#include "simstruc.h"
/*====================*
* S-function methods *
*====================*/
7-39
7 Implementing Block Features
ssSetNumContStates(S, 0);
ssSetNumDiscStates(S, 2);
ssSetNumSampleTimes(S, 1);
ssSetNumRWork(S, 0);
ssSetNumIWork(S, 0);
ssSetNumPWork(S, 0);
ssSetNumModes(S, 0);
ssSetNumNonsampledZCs(S, 0);
#define MDL_INITIALIZE_CONDITIONS
/* Function: mdlInitializeConditions ========================================
* Abstract:
* Initialize both discrete states to one.
*/
static void mdlInitializeConditions(SimStruct *S)
{
real_T *x0 = ssGetRealDiscStates(S);
int_T lp;
for (lp=0;lp<2;lp++) {
*x0++=1.0;
}
}
7-40
S-Function Examples
/* y=Cx+Du */
y[0]=C[0][0]*x[0]+C[0][1]*x[1]+D[0][0]*U(0)+D[0][1]*U(1);
y[1]=C[1][0]*x[0]+C[1][1]*x[1]+D[1][0]*U(0)+D[1][1]*U(1);
}
#define MDL_UPDATE
/* Function: mdlUpdate ======================================================
* Abstract:
* xdot = Ax + Bu
*/
static void mdlUpdate(SimStruct *S, int_T tid)
{
real_T tempX[2] = {0.0, 0.0};
real_T *x = ssGetRealDiscStates(S);
InputRealPtrsType uPtrs = ssGetInputPortRealSignalPtrs(S,0);
/* xdot=Ax+Bu */
tempX[0]=A[0][0]*x[0]+A[0][1]*x[1]+B[0][0]*U(0)+B[0][1]*U(1);
tempX[1]=A[1][0]*x[0]+A[1][1]*x[1]+B[1][0]*U(0)+B[1][1]*U(1);
x[0]=tempX[0];
x[1]=tempX[1];
}
7-41
7 Implementing Block Features
matlabroot/simulink/src/mixedm.c
/* File : mixedm.c
* Abstract:
*
* An example S-function illustrating multiple sample times by implementing
* integrator -> ZOH(Ts=1second) -> UnitDelay(Ts=1second)
* with an initial condition of 1.
* (e.g. an integrator followed by unit delay operation).
*
* For more details about S-functions, see simulink/src/sfuntmpl_doc.c
*
* Copyright 1990-2000 The MathWorks, Inc.
* $Revision: 1.11 $
*/
7-42
S-Function Examples
#include "simstruc.h"
/*====================*
* S-function methods *
*====================*/
ssSetNumContStates(S, 1);
ssSetNumDiscStates(S, 1);
ssSetNumRWork(S, 1); /* for zoh output feeding the delay operator */
ssSetNumSampleTimes(S, 2);
} /* end mdlInitializeSizes */
7-43
7 Implementing Block Features
ssSetSampleTime(S, 1, 1.0);
ssSetOffsetTime(S, 1, 0.0);
} /* end mdlInitializeSampleTimes */
#define MDL_INITIALIZE_CONDITIONS
/* Function: mdlInitializeConditions ==========================================
* Abstract:
* Initialize both continuous states to one.
*/
static void mdlInitializeConditions(SimStruct *S)
{
real_T *xC0 = ssGetContStates(S);
real_T *xD0 = ssGetRealDiscStates(S);
xC0[0] = 1.0;
xD0[0] = 1.0;
} /* end mdlInitializeConditions */
/* y=xD */
if (ssIsSampleHit(S, 1, tid)) {
real_T *y = ssGetOutputPortRealSignal(S,0);
real_T *xD = ssGetRealDiscStates(S);
y[0]=xD[0];
}
} /* end mdlOutputs */
#define MDL_UPDATE
7-44
S-Function Examples
/* xD=xC */
if (ssIsSampleHit(S, 1, tid)) {
real_T *xD = ssGetRealDiscStates(S);
real_T *zoh = ssGetRWork(S);
xD[0]=*zoh;
}
} /* end mdlUpdate */
#define MDL_DERIVATIVES
/* Function: mdlDerivatives =================================================
* Abstract:
* xdot = U
*/
static void mdlDerivatives(SimStruct *S)
{
real_T *dx = ssGetdX(S);
InputRealPtrsType uPtrs = ssGetInputPortRealSignalPtrs(S,0);
/* xdot=U */
dx[0]=U(0);
} /* end mdlDerivatives */
7-45
7 Implementing Block Features
The macro ssGetT gets the simulation time t. The second input to the block,
(*u[1]), is added to t, and the macro ssSetTNext sets the time of next hit equal
to t+(*u[1]), delaying the output by the amount of time set in (*u[1]).
matlabroot/simulink/src/vsfunc.c
/* File : vsfunc.c
* Abstract:
*
* Example C-file S-function for defining a continuous system.
*
* Variable step S-function example.
* This example S-function illustrates how to create a variable step
* block in Simulink. This block implements a variable step delay
* in which the first input is delayed by an amount of time determined
* by the second input:
*
* dt = u(2)
* y(t+dt) = u(t)
*
* For more details about S-functions, see simulink/src/sfuntmpl_doc.c.
*
* Copyright 1990-2000 The MathWorks, Inc.
7-46
S-Function Examples
* $Revision: 1.10 $
*/
#include "simstruc.h"
ssSetNumContStates(S, 0);
ssSetNumDiscStates(S, 1);
ssSetNumSampleTimes(S, 1);
ssSetNumRWork(S, 0);
ssSetNumIWork(S, 0);
ssSetNumPWork(S, 0);
ssSetNumModes(S, 0);
ssSetNumNonsampledZCs(S, 0);
7-47
7 Implementing Block Features
#define MDL_INITIALIZE_CONDITIONS
/* Function: mdlInitializeConditions ========================================
* Abstract:
* Initialize discrete state to zero.
*/
static void mdlInitializeConditions(SimStruct *S)
{
real_T *x0 = ssGetRealDiscStates(S);
x0[0] = 0.0;
}
#define MDL_GET_TIME_OF_NEXT_VAR_HIT
static void mdlGetTimeOfNextVarHit(SimStruct *S)
{
InputRealPtrsType uPtrs = ssGetInputPortRealSignalPtrs(S,0);
7-48
S-Function Examples
y[0] = x[0];
}
#define MDL_UPDATE
/* Function: mdlUpdate ========================================================
* Abstract:
* This function is called once for every major integration time step.
* Discrete states are typically updated here, but this function is useful
* for performing any tasks that should only take place once per integration
* step.
*/
static void mdlUpdate(SimStruct *S, int_T tid)
{
real_T *x = ssGetRealDiscStates(S);
InputRealPtrsType uPtrs = ssGetInputPortRealSignalPtrs(S,0);
x[0]=U(0);
}
7-49
7 Implementing Block Features
matlabroot/simulink/src/sfun_zc_sat.c
/* File : sfun_zc_sat.c
* Abstract:
*
* Example of an S-function which has nonsampled zero crossings to
* implement a saturation function. This S-function is designed to be
* used with a variable or fixed step solver.
*
* A saturation is described by three equations
*
* (1) y = UpperLimit
* (2) y = u
* (3) y = LowerLimit
*
* and a set of inequalities that specify which equation to use
*
* if UpperLimit < u then use (1)
* if LowerLimit <= u <= UpperLimit then use (2)
* if u < LowerLimit then use (3)
*
* A key fact is that the valid equation 1, 2, or 3, can change at
* any instant. Nonsampled zero crossing support helps the variable step
* solvers locate the exact instants when behavior switches from one equation
* to another.
*
* Copyright 1990-2000 The MathWorks, Inc.
* $Revision: 1.10 $
*/
#include "simstruc.h"
/*========================*
* General Defines/macros *
*========================*/
/*
* Make access to mxArray pointers for parameters more readable.
*/
#define P_PAR_UPPER_LIMIT ( ssGetSFcnParam(S,I_PAR_UPPER_LIMIT) )
7-50
S-Function Examples
#define MDL_CHECK_PARAMETERS
#if defined(MDL_CHECK_PARAMETERS) && defined(MATLAB_MEX_FILE)
/*
* check parameter basics
*/
for ( i = 0; i < N_PAR; i++ ) {
if ( mxIsEmpty( ssGetSFcnParam(S,i) ) ||
mxIsSparse( ssGetSFcnParam(S,i) ) ||
mxIsComplex( ssGetSFcnParam(S,i) ) ||
!mxIsNumeric( ssGetSFcnParam(S,i) ) ) {
msg = "Parameters must be real vectors.";
goto EXIT_POINT;
}
}
/*
* Check sizes of parameters.
*/
numUpperLimit = mxGetNumberOfElements( P_PAR_UPPER_LIMIT );
numLowerLimit = mxGetNumberOfElements( P_PAR_LOWER_LIMIT );
if ( ( numUpperLimit != 1 ) &&
( numLowerLimit != 1 ) &&
( numUpperLimit != numLowerLimit ) ) {
msg = "Number of input and output values must be equal.";
goto EXIT_POINT;
}
/*
* Error exit point
*/
EXIT_POINT:
if (msg != NULL) {
ssSetErrorStatus(S, msg);
}
}
#endif /* MDL_CHECK_PARAMETERS */
7-51
7 Implementing Block Features
/*
* Set and Check parameter count
*/
ssSetNumSFcnParams(S, N_PAR);
#if defined(MATLAB_MEX_FILE)
if (ssGetNumSFcnParams(S) == ssGetSFcnParamsCount(S)) {
mdlCheckParameters(S);
if (ssGetErrorStatus(S) != NULL) {
return;
}
} else {
return; /* Parameter mismatch will be reported by Simulink */
}
#endif
/*
* Get parameter size info.
*/
numUpperLimit = mxGetNumberOfElements( P_PAR_UPPER_LIMIT );
numLowerLimit = mxGetNumberOfElements( P_PAR_LOWER_LIMIT );
/*
* states
*/
ssSetNumContStates(S, 0);
ssSetNumDiscStates(S, 0);
/*
* outputs
* The upper and lower limits are scalar expanded
* so their size determines the size of the output
* only if at least one of them is not scalar.
*/
if (!ssSetNumOutputPorts(S, 1)) return;
7-52
S-Function Examples
if ( maxNumLimit > 1 ) {
ssSetOutputPortWidth(S, 0, maxNumLimit);
} else {
ssSetOutputPortWidth(S, 0, DYNAMICALLY_SIZED);
}
/*
* inputs
* If the upper or lower limits are not scalar then
* the input is set to the same size. However, the
* ssSetOptions below allows the actual width to
* be reduced to 1 if needed for scalar expansion.
*/
if (!ssSetNumInputPorts(S, 1)) return;
ssSetInputPortDirectFeedThrough(S, 0, 1 );
if ( maxNumLimit > 1 ) {
ssSetInputPortWidth(S, 0, maxNumLimit);
} else {
ssSetInputPortWidth(S, 0, DYNAMICALLY_SIZED);
}
/*
* sample times
*/
ssSetNumSampleTimes(S, 1);
/*
* work
*/
ssSetNumRWork(S, 0);
ssSetNumIWork(S, 0);
ssSetNumPWork(S, 0);
/*
* Modes and zero crossings:
* If we have a variable step solver and this block has a continuous
* sample time, then
* o One mode element will be needed for each scalar output
* in order to specify which equation is valid (1), (2), or (3).
* o Two ZC elements will be needed for each scalar output
* in order to help the solver find the exact instants
* at which either of the two possible "equation switches"
* One will be for the switch from eq. (1) to (2);
* the other will be for eq. (2) to (3) and vise versa.
* otherwise
* o No modes and nonsampled zero crossings will be used.
*
*/
ssSetNumModes(S, DYNAMICALLY_SIZED);
ssSetNumNonsampledZCs(S, DYNAMICALLY_SIZED);
7-53
7 Implementing Block Features
/*
* options
* o No mexFunctions and no problematic mxFunctions are called
* so the exception free code option safely gives faster simulations.
* o Scalar expansion of the inputs is desired. The option provides
* this without the need to write mdlSetOutputPortWidth and
* mdlSetInputPortWidth functions.
*/
ssSetOptions(S, ( SS_OPTION_EXCEPTION_FREE_CODE |
SS_OPTION_ALLOW_INPUT_SCALAR_EXPANSION));
} /* end mdlInitializeSizes */
#define MDL_SET_WORK_WIDTHS
#if defined(MDL_SET_WORK_WIDTHS) && defined(MATLAB_MEX_FILE)
/* Function: mdlSetWorkWidths ===============================================
* The width of the Modes and the ZCs depends on the width of the output.
* This width is not always known in mdlInitializeSizes so it is handled
* here.
*/
static void mdlSetWorkWidths(SimStruct *S)
{
int nModes;
int nNonsampledZCs;
if (ssIsVariableStepSolver(S) &&
ssGetSampleTime(S,0) == CONTINUOUS_SAMPLE_TIME &&
ssGetOffsetTime(S,0) == 0.0) {
/*
* modes and zero crossings
* o One mode element will be needed for each scalar output
* in order to specify which equation is valid (1), (2), or (3).
* o Two ZC elements will be needed for each scalar output
* in order to help the solver find the exact instants
* at which either of the two possible "equation switches"
7-54
S-Function Examples
7-55
7 Implementing Block Features
/*
* Set index and increment for input signal, upper limit, and lower limit
* parameters so that each gives scalar expansion if needed.
*/
int_T uIdx = 0;
int_T uInc = ( ssGetInputPortWidth(S,0) > 1 );
const real_T *upperLimit = mxGetPr( P_PAR_UPPER_LIMIT );
int_T upperLimitInc = ( mxGetNumberOfElements( P_PAR_UPPER_LIMIT ) > 1 );
const real_T *lowerLimit = mxGetPr( P_PAR_LOWER_LIMIT );
int_T lowerLimitInc = ( mxGetNumberOfElements( P_PAR_LOWER_LIMIT ) > 1 );
if (ssGetNumNonsampledZCs(S) == 0) {
/*
* This block is being used with a fixed-step solver or it has
* a noncontinuous sample time, so we always saturate.
*/
for (iOutput = 0; iOutput < numOutput; iOutput++) {
if (*uPtrs[uIdx] >= *upperLimit) {
*y++ = *upperLimit;
} else if (*uPtrs[uIdx] > *lowerLimit) {
*y++ = *uPtrs[uIdx];
} else {
*y++ = *lowerLimit;
}
upperLimit += upperLimitInc;
lowerLimit += lowerLimitInc;
uIdx += uInc;
}
} else {
/*
* This block is being used with a variable-step solver.
*/
int_T *mode = ssGetModeVector(S);
/*
* Specify indices for each equation.
7-56
S-Function Examples
*/
enum { UpperLimitEquation, NonLimitEquation, LowerLimitEquation };
/*
* Update the Mode Vector ONLY at the beginning of a MajorTimeStep
*/
if ( ssIsMajorTimeStep(S) ) {
/*
* Specify the mode, ie the valid equation for each output scalar.
*/
for ( iOutput = 0; iOutput < numOutput; iOutput++ ) {
if ( *uPtrs[uIdx] > *upperLimit ) {
/*
* Upper limit eq is valid.
*/
mode[iOutput] = UpperLimitEquation;
} else if ( *uPtrs[uIdx] < *lowerLimit ) {
/*
* Lower limit eq is valid.
*/
mode[iOutput] = LowerLimitEquation;
} else {
/*
* Nonlimit eq is valid.
*/
mode[iOutput] = NonLimitEquation;
}
/*
* Adjust indices to give scalar expansion if needed.
*/
uIdx += uInc;
upperLimit += upperLimitInc;
lowerLimit += lowerLimitInc;
}
/*
* Reset index to input and limits.
*/
uIdx = 0;
upperLimit = mxGetPr( P_PAR_UPPER_LIMIT );
lowerLimit = mxGetPr( P_PAR_LOWER_LIMIT );
} /* end IsMajorTimeStep */
/*
* For both MinorTimeSteps and MajorTimeSteps calculate each scalar
* output using the equation specified by the mode vector.
*/
for ( iOutput = 0; iOutput < numOutput; iOutput++ ) {
if ( mode[iOutput] == UpperLimitEquation ) {
/*
* Upper limit eq.
*/
7-57
7 Implementing Block Features
*y++ = *upperLimit;
} else if ( mode[iOutput] == LowerLimitEquation ) {
/*
* Lower limit eq.
*/
*y++ = *lowerLimit;
} else {
/*
* Nonlimit eq.
*/
*y++ = *uPtrs[uIdx];
}
/*
* Adjust indices to give scalar expansion if needed.
*/
uIdx += uInc;
upperLimit += upperLimitInc;
lowerLimit += lowerLimitInc;
}
}
} /* end mdlOutputs */
#define MDL_ZERO_CROSSINGS
#if defined(MDL_ZERO_CROSSINGS) && (defined(MATLAB_MEX_FILE) || defined(NRT))
7-58
S-Function Examples
/*
* Set index and increment for the input signal, upper limit, and lower
* limit parameters so that each gives scalar expansion if needed.
*/
int_T uIdx = 0;
int_T uInc = ( ssGetInputPortWidth(S,0) > 1 );
real_T *upperLimit = mxGetPr( P_PAR_UPPER_LIMIT );
int_T upperLimitInc = ( mxGetNumberOfElements( P_PAR_UPPER_LIMIT ) > 1 );
real_T *lowerLimit = mxGetPr( P_PAR_LOWER_LIMIT );
int_T lowerLimitInc = ( mxGetNumberOfElements( P_PAR_LOWER_LIMIT ) > 1 );
/*
* For each output scalar, give the solver a measure of "how close things
* are" to an equation switch.
*/
for ( iOutput = 0; iOutput < numOutput; iOutput++ ) {
7-59
7 Implementing Block Features
/*
* Adjust indices to give scalar expansion if needed.
*/
uIdx += uInc;
upperLimit += upperLimitInc;
lowerLimit += lowerLimitInc;
}
}
7-60
S-Function Examples
matlabroot/simulink/src/stvctf.c
/*
* File : stvctf.c
* Abstract:
* Time Varying Continuous Transfer Function block
*
* This S-function implements a continous time transfer function
* whose transfer function polynomials are passed in via the input
* vector. This is useful for continuous time adapative control
* applications.
*
* This S-function is also an example of how to "use banks" to avoid
* problems with computing derivatives when a continuous output has
* discontinuities. The consistency checker can be used to verify that
* your S-function is correct with respect to always maintaining smooth
* and consistent signals for the integrators. By consistent we mean that
* two mdlOutput calls at major time t and minor time t are always the
* same. The consistency checker is enabled on the diagnostics page of the
* simulation parameters dialog box. The update method of this S-function
* modifies the coefficients of the transfer function, which cause the
* output to "jump." To have the simulation work properly, we need to let
* the solver know of these discontinuities by setting
* ssSetSolverNeedsReset and then we need to use multiple banks of
* coefficients so the coefficients used in the major time step output
* and the minor time step outputs are the same. In the simulation loop
* we have:
* Loop:
* o Output in major time step at time t
* o Update in major time step at time t
* o Integrate (minor time step):
* o Consistency check: recompute outputs at time t and compare
* with current outputs.
* o Derivatives at time t
* o One or more Output,Derivative evaluations at time t+k
* where k <= step_size to be taken.
* o Compute state, x
* o t = t + step_size
* End_Integrate
* End_Loop
* Another purpose of the consistency checker is used to verify that when
7-61
7 Implementing Block Features
#include "simstruc.h"
/*
* Defines for easy access to the numerator and denominator polynomials
* parameters
*/
#define NUM(S) ssGetSFcnParam(S, 0)
#define DEN(S) ssGetSFcnParam(S, 1)
#define TS(S) ssGetSFcnParam(S, 2)
#define NPARAMS 3
#define MDL_CHECK_PARAMETERS
#if defined(MDL_CHECK_PARAMETERS) && defined(MATLAB_MEX_FILE)
/* Function: mdlCheckParameters =============================================
* Abstract:
* Validate our parameters to verify:
* o The numerator must be of a lower order than the denominator.
* o The sample time must be a real positive nonzero value.
*/
static void mdlCheckParameters(SimStruct *S)
{
int_T i;
7-62
S-Function Examples
mxIsSparse( ssGetSFcnParam(S,i)) ||
mxIsComplex( ssGetSFcnParam(S,i)) ||
!mxIsNumeric( ssGetSFcnParam(S,i)) ) {
ssSetErrorStatus(S,"Parameters must be real finite vectors");
return;
}
pr = mxGetPr(ssGetSFcnParam(S,i));
nEls = mxGetNumberOfElements(ssGetSFcnParam(S,i));
for (el = 0; el < nEls; el++) {
if (!mxIsFinite(pr[el])) {
ssSetErrorStatus(S,"Parameters must be real finite vectors");
return;
}
}
}
7-63
7 Implementing Block Features
/*
* Define the characteristics of the block:
*
* Number of continuous states: length of denominator - 1
* Inputs port width 2 * (NumContStates+1) + 1
* Output port width 1
* DirectFeedThrough: 0 (Although this should be computed.
* We'll assume coefficients entered
* are strictly proper).
* Number of sample times: 2 (continuous and discrete)
* Number of Real work elements: 4*NumCoeffs
* (Two banks for num and den coeff's:
* NumBank0Coeffs
* DenBank0Coeffs
* NumBank1Coeffs
* DenBank1Coeffs)
* Number of Integer work elements: 2 (indicator of active bank 0 or 1
* and flag to indicate when banks
* have been updated).
*
* The number of inputs arises from the following:
* o 1 input (u)
* o the numerator and denominator polynomials each have NumContStates+1
* coefficients
*/
nCoeffs = mxGetNumberOfElements(DEN(S));
nContStates = nCoeffs - 1;
ssSetNumContStates(S, nContStates);
ssSetNumDiscStates(S, 0);
if (!ssSetNumOutputPorts(S,1)) return;
ssSetOutputPortWidth(S, 0, 1);
ssSetOutputPortSampleTime(S, 0, CONTINUOUS_SAMPLE_TIME);
ssSetOutputPortOffsetTime(S, 0, 0);
ssSetNumSampleTimes(S, 2);
ssSetNumRWork(S, 4 * nCoeffs);
ssSetNumIWork(S, 2);
ssSetNumPWork(S, 0);
7-64
S-Function Examples
ssSetNumModes(S, 0);
ssSetNumNonsampledZCs(S, 0);
} /* end mdlInitializeSizes */
/*
* the second, discrete sample time, is user provided
*/
ssSetSampleTime(S, 1, mxGetPr(TS(S))[0]);
ssSetOffsetTime(S, 1, 0.0);
} /* end mdlInitializeSampleTimes */
#define MDL_INITIALIZE_CONDITIONS
/* Function: mdlInitializeConditions ==========================================
* Abstract:
* Initalize the states, numerator and denominator coefficients.
*/
static void mdlInitializeConditions(SimStruct *S)
{
int_T i;
int_T nContStates = ssGetNumContStates(S);
real_T *x0 = ssGetContStates(S);
int_T nCoeffs = nContStates + 1;
real_T *numBank0 = ssGetRWork(S);
real_T *denBank0 = numBank0 + nCoeffs;
int_T *activeBank = ssGetIWork(S);
/*
7-65
7 Implementing Block Features
/*
* Set up the initial numerator and denominator.
*/
{
const real_T *numParam = mxGetPr(NUM(S));
int numParamLen = mxGetNumberOfElements(NUM(S));
/*
* Normalize if this transfer function has direct feedthrough.
*/
for (i = 1; i < nCoeffs; i++) {
numBank0[i] -= denBank0[i]*numBank0[0];
}
/*
* Indicate bank0 is active (i.e. bank1 is oldest).
*/
*activeBank = 0;
} /* end mdlInitializeConditions */
7-66
S-Function Examples
if (ssIsContinuousTask(S,tid)) {
int i;
real_T *num;
int nContStates = ssGetNumContStates(S);
real_T *x = ssGetContStates(S);
int_T nCoeffs = nContStates + 1;
InputRealPtrsType uPtrs = ssGetInputPortRealSignalPtrs(S,0);
real_T *y = ssGetOutputPortRealSignal(S,0);
int_T *activeBank = ssGetIWork(S);
/*
* Switch banks we've updated them in mdlUpdate and we're no longer
* in a minor time step.
*/
if (ssIsMajorTimeStep(S)) {
int_T *banksUpdated = ssGetIWork(S) + 1;
if (*banksUpdated) {
*activeBank = !(*activeBank);
*banksUpdated = 0;
/*
* Need to tell the solvers that the derivatives are no
* longer valid.
*/
ssSetSolverNeedsReset(S);
}
}
num = ssGetRWork(S) + (*activeBank) * (2*nCoeffs);
/*
* The continuous system is evaluated using a controllable state space
* representation of the transfer function. This implies that the
* output of the system is equal to:
*
* y(t) = Cx(t) + Du(t)
* = [ b1 b2 ... bn]x(t) + b0u(t)
*
* where b0, b1, b2, ... are the coefficients of the numerator
* polynomial:
*
* B(s) = b0 s^n + b1 s^n-1 + b2 s^n-2 + ... + bn-1 s + bn
*/
*y = *num++ * (*uPtrs[0]);
for (i = 0; i < nContStates; i++) {
*y += *num++ * *x++;
}
}
} /* end mdlOutputs */
#define MDL_UPDATE
/* Function: mdlUpdate ========================================================
* Abstract:
7-67
7 Implementing Block Features
if (ssIsSampleHit(S, 1, tid)) {
int_T i;
InputRealPtrsType uPtrs = ssGetInputPortRealSignalPtrs(S,0);
int_T uIdx = 1;/*1st coeff is after signal input*/
int_T nContStates = ssGetNumContStates(S);
int_T nCoeffs = nContStates + 1;
int_T bankToUpdate = !ssGetIWork(S)[0];
real_T *num = ssGetRWork(S)+bankToUpdate*2*nCoeffs;
real_T *den = num + nCoeffs;
real_T den0;
int_T allZero;
/*
* Get the first denominator coefficient. It will be used
* for normalizing the numerator and denominator coefficients.
*
* If all inputs are zero, we probably could have unconnected
* inputs, so use the parameter as the first denominator coefficient.
*/
den0 = *uPtrs[uIdx+nCoeffs];
if (den0 == 0.0) {
den0 = mxGetPr(DEN(S))[0];
}
/*
* Grab the numerator.
*/
allZero = 1;
for (i = 0; (i < nCoeffs) && allZero; i++) {
allZero &= *uPtrs[uIdx+i] == 0.0;
}
7-68
S-Function Examples
} else {
for (i = 0; i < nCoeffs; i++) {
*num++ = *uPtrs[uIdx++] / den0;
}
}
/*
* Grab the denominator.
*/
allZero = 1;
for (i = 0; (i < nCoeffs) && allZero; i++) {
allZero &= *uPtrs[uIdx+i] == 0.0;
}
den0 = denParam[0];
for (i = 0; i < denParamLen; i++) {
*den++ = *denParam++ / den0;
}
} else {
for (i = 0; i < nCoeffs; i++) {
*den++ = *uPtrs[uIdx++] / den0;
}
}
/*
* Normalize if this transfer function has direct feedthrough.
*/
num = ssGetRWork(S) + bankToUpdate*2*nCoeffs;
den = num + nCoeffs;
for (i = 1; i < nCoeffs; i++) {
num[i] -= den[i]*num[0];
}
/*
* Indicate oldest bank has been updated.
*/
ssGetIWork(S)[1] = 1;
}
} /* end mdlUpdate */
#define MDL_DERIVATIVES
/* Function: mdlDerivatives ===================================================
* Abstract:
* The drivatives for this block are computed by using a controllable
* state-space representation of the transfer function.
*/
7-69
7 Implementing Block Features
/*
* The continuous system is evaluated using a controllable state-space
* representation of the transfer function. This implies that the
* next continuous states are computed using:
*
* dx = Ax(t) + Bu(t)
* = [-a1 -a2 ... -an] [x1(t)] + [u(t)]
* [ 1 0 ... 0] [x2(t)] + [0]
* [ 0 1 ... 0] [x3(t)] + [0]
* [ . . ... .] . + .
* [ . . ... .] . + .
* [ . . ... .] . + .
* [ 0 0 ... 1 0] [xn(t)] + [0]
*
* where a1, a2, ... are the coefficients of the numerator polynomial:
*
* A(s) = s^n + a1 s^n-1 + a2 s^n-2 + ... + an-1 s + an
*/
dx[0] = -den[1] * x[0] + *uPtrs[0];
for (i = 1; i < nContStates; i++) {
dx[i] = x[i-1];
dx[0] -= den[i+1] * x[i];
}
} /* end mdlDerivatives */
7-70
S-Function Examples
#else
#include "cg_sfun.h" /* Code generation registration function */
#endif
7-71
7 Implementing Block Features
7-72
8
Writing S-Functions for
Real-Time Workshop
Introduction . . . . . . . . . . . . . . . . . . . . 8-2
Classes of Problems Solved by S-Functions . . . . . . . . 8-2
Types of S-Functions . . . . . . . . . . . . . . . . . 8-3
Basic Files Required for Implementation . . . . . . . . . 8-5
Introduction
This chapter describes how to create S-functions that work seamlessly with
both Simulink and the Real-Time Workshop. It begins with basic concepts and
concludes with an example of how to create a highly optimized direct-index
lookup table S-function block.
This chapter assumes that you understand these concepts:
• Level 2 S-functions
• Target Language Compiler (TLC)
• The basics of how the Real-Time Workshop creates generated code
See the Target Language Compiler Reference Guide, and the Real-Time
Workshop User’s Guide for more information about these subjects.
A note on terminology: when this chapter refers actions performed by the
Target Language Compiler, including parsing, caching, creating buffers, etc.,
the name Target Language Compiler is spelled out fully. When referring to
code written in the Target Language Compiler syntax, this chapter uses the
abbreviation TLC.
Note The guidelines presented in this chapter are for Real-Time Workshop
users. Even if you do not currently use the Real-Time Workshop, we
recommend that you follow the guidelines presented in this chapter when
writing S-functions, especially if you are creating general-purpose S-functions.
8-2
Introduction
Types of S-Functions
The implementation of S-functions changes based on your requirements. This
chapter discusses the typical problems that you may face and how to create
S-functions for applications that need to work with Simulink and the
Real-Time Workshop. These are some (informally defined) common situations:
1 “I’m not concerned with efficiency. I just want to write one version of my
algorithm and have it work in Simulink and the Real-Time Workshop
automatically.”
8-3
8 Writing S-Functions for Real-Time Workshop
1 Noninlined S-function
2 Wrapper S-function
Noninlined S-Functions
A noninlined S-function is a C-MEX S-function that is treated identically by
Simulink and the Real-Time Workshop. In general, you implement your
algorithm once according to the S-function API. Simulink and the Real-Time
Workshop call the S-function routines (e.g., mdlOutputs) at the appropriate
points during model execution.
Significant memory and computation resources are required for each instance
of a noninlined S-function block. However, this routine of incorporating
algorithms into Simulink and the Real-Time Workshop is typical during the
prototyping phase of a project where efficiency is not important. The advantage
gained by foregoing efficiency is the ability to change model parameters and/or
structures rapidly.
Note that writing a noninlined S-function does not involve any TLC coding.
Noninlined S-functions are the default case for the Real-Time Workshop in the
sense that once you’ve built a C-MEX S-function in your model, there is no
additional preparation prior to clicking Build in the Real-Time Workshop
Page of the Simulation Parameters dialog box for your model.
Wrapper S-Functions
A wrapper S-function is ideal for interfacing hand-written code or a large
algorithm that is encapsulated within a few procedures. In this situation,
usually the procedures reside in modules that are separate from the C-MEX
S-function. The S-function module typically contains a few calls to your
procedures. Since the S-function module does not contain any parts of your
algorithm, but only calls your code, it is referred to as a wrapper S-function.
8-4
Introduction
8-5
8 Writing S-Functions for Real-Time Workshop
Note The term inline should not be confused with the C++ inline keyword. In
MathWorks terminology, inline means to specify a textual string in place of
the call to the general S-function API routines (e.g., mdlOutputs). For example,
when we say that a TLC file is used to inline an S-function, we mean that the
generated code contains the appropriate C code that would normally appear
within the S-function routines and the S-function itself has been removed
from the build process.
8-6
Noninlined S-Functions
Noninlined S-Functions
Noninlined S-functions are identified by the absence of an sfunction.tlc file
for your S-function (sfunction.mex). When placing a noninlined S-function in
a model that is to be used with the Real-Time Workshop, the following
MATLAB API functions are supported:
• mxGetEps
• mxGetInf
• mxGetM
• mxGetN
• mxGetNaN
• mxGetPr — Note: using mxGetPr on an empty matrix does not return NULL;
rather, it returns a random value. Therefore, you should protect calls to
mxGetPr with mxIsEmpty.
• mxGetScalar
• mxGetString
• mxIsEmpty
• mxIsFinite
• mxIsInf
In addition, parameters to S-functions can only be of type double precision or
characters contained in scalars, vectors, or 2-D matrices. To obtain more
flexibility in the type of parameters you can supply to S-functions or the
operations in the S-function, you need to inline your S-function and (possibly)
use a mdlRTW S-function routine.
then specify the names of the modules without the extension using the
command
8-7
8 Writing S-Functions for Real-Time Workshop
set_param(sfun_block,'SFunctionModules','sfun_module1 sfun_module2')
8-8
Writing Wrapper S-Functions
8-9
8 Writing S-Functions for Real-Time Workshop
then you must create a fully inlined TLC file for your S-function.
8-10
Writing Wrapper S-Functions
mdlOutputs in my_alg.c
wrapsfcn.mex ...
calls external real_T my_alg(real_T u)
function my_alg. {
...
y=f(u);
}
*The dotted line above would be the path taken if the S-function did not
have a TLC wrapper file. If there is no TLC wrapper file, the generated code
calls mdlOutputs.
8-11
8 Writing S-Functions for Real-Time Workshop
There are two files associated with wrapsfcn block, the S-function wrapper and
the C code that contains the algorithm. This is the S-function wrapper code for
this example, called wrapsfcn.c.
#define S_FUNCTION_NAME wrapsfcn
#define S_FUNCTION_LEVEL 2
#include “simstruc.h”
Declare my_alg as
extern real_T my_alg(real_T u);
extern.
/*
* mdlInitializeSizes - initialize the sizes array
*/
static void mdlInitializeSizes(SimStruct *S)
{
if (!ssSetNumOutputPorts(S,1)) return;
ssSetOutputPortWidth(S, 0, 1);
ssSetNumSampleTimes( S, 1);
}
8-12
Writing Wrapper S-Functions
/*
* mdlInitializeSampleTimes - indicate that this S-function runs
*at the rate of the source (driving block)
*/
static void mdlInitializeSampleTimes(SimStruct *S)
{
ssSetSampleTime(S, 0, INHERITED_SAMPLE_TIME);
ssSetOffsetTime(S, 0, 0.0);
}
/*
* mdlOutputs - compute the outputs by calling my_alg, which
*resides in another module, my_alg.c
*/
static void mdlOutputs(SimStruct *S, int_T tid)
{
InputRealPtrsType uPtrs = ssGetInputPortRealSignalPtrs(S,0);
Place the call to real_T *y = ssGetOutputPortRealSignal(S,0);
my_alg in *y = my_alg(*uPtrs[0]);
mdlOutputs. }
/*
* mdlTerminate - called when the simulation is terminated.
*/
static void mdlTerminate(SimStruct *S)
{
}
8-13
8 Writing S-Functions for Real-Time Workshop
When creating a TLC S-function wrapper, the goal is to have the Real-Time
Workshop embed the same type of call in the generated code.
It is instructive to look at how the Real-Time Workshop executes S-functions
that are not inlined. A noninlined S-function is identified by the absence of the
file sfunction.tlc and the existence of sfunction.mex. When generating code
for a noninlined S-function, the Real-Time Workshop generates a call to
mdlOutputs through a function pointer that, in this example, then calls my_alg.
The code generated when using grt.tlc as the system target file without
wrapsfcn.tlc is
<Generated code comments for wrapper model with noninlined wrapsfcn S-function>
#include <math.h>
#include <string.h>
#include “wrapper.h”
#include “wrapper.prm”
8-14
Writing Wrapper S-Functions
/* Terminate function */
void MdlTerminate(void)
{
/* Level2 S-Function Block: <Root>/S-Function (wrapsfcn) */
Noninlined {
S-functions require a SimStruct *rts = ssGetSFunction(rtS, 0);
SimStruct object and sfcnTerminate(rts);
}
the call to the }
#include “wrapper.reg”
/* [EOF] wrapper.c */
How to Inline
The generated code makes the call to your S-function, wrapsfcn.c, in
MdlOutputs by using this code.
SimStruct *rts = ssGetSFunction(rtS, 0);
sfcnOutputs(rts, tid);
8-15
8 Writing S-Functions for Real-Time Workshop
to your C algorithm (my_alg), you can eliminate both the SimStruct and the
extra function call, thereby improving the efficiency and reducing the size of
the generated code.
Inlining a wrapper S-function requires an sfunction.tlc file for the
S-function; this file must contain the function call to my_alg. This picture
shows the relationships between the algorithm, the wrapper S-function, and
the sfunction.tlc file.
wrapper.c
my_alg.c
...
myalg() MdlOutputs
{ {
<C code here> ...
} y = my_alg();
...
}
...
The wrapsfcn.tlc file tells the
Real-Time Workshop how to inline the
call to my_alg using this statement:
wrapsfcn.tlc
...
%<y> = my_alg(%<u>);
...
To inline this call, you have to place your function call into an sfunction.tlc
file with the same name as the S-function (in this example, wrapsfcn.tlc).
This causes the Target Language Compiler to override the default method of
placing calls to your S-function in the generated code.
8-16
Writing Wrapper S-Functions
The first section of this code directs the Real-Time Workshop to inline the
wrapsfcn S-function block and generate the code in C:
%implements "wrapsfcn" "C"
The next task is to tell the Real-Time Workshop that the routine, my_alg, needs
to be declared external in the generated wrapper.h file for any wrapsfcn
S-function blocks in the model. You only need to do this once for all wrapsfcn
S-function blocks, so use the BlockTypeSetup function. In this function, you tell
the Target Language Compiler to create a buffer and cache the my_alg as
extern in the wrapper.h generated header file.
The final step is the actual inlining of the call to the function my_alg. This is
done by the Outputs function. In this function, you load the input and output
and call place a direct call to my_alg. The call is embedded in wrapper.c.
8-17
8 Writing S-Functions for Real-Time Workshop
8-18
Fully Inlined S-Functions
use:
%<y> = 2.0 * %<u>;
The Target Language Compiler has replaced the call to my_alg with the
algorithm itself.
8-19
8 Writing S-Functions for Real-Time Workshop
that contains multiple ports. You may find that looking at this example will aid
in the understanding of fully inlined TLC files.
8-20
Fully Inlined S-Function with the mdlRTW Routine
mdlRTW does this by placing information into the model.rtw file. The mdlRTW
routine is described in the text file matlabroot/simulink/src/
sfuntmpl_doc.c.
As an example of how to use the mdlRTW function, this section discusses the
steps you must take to create a direct-index lookup S-function. Look-up tables
are a collection of ordered data points of a function. Typically, these tables use
some interpolation scheme to approximate values of the associated function
between known data points. To incorporate the example lookup table algorithm
in Simulink, the first step is to write an S-function that executes the algorithm
in mdlOutputs. To produce the most efficient C code, the next step is to create
a corresponding TLC file to eliminate computational overhead and improve the
performance of the lookup computations.
For your convenience, Simulink provides support for two general purpose
lookup 1-D and 2-D algorithms. You can use these algorithms as they are or
create a custom lookup table S-function to fit your requirements. This section
demonstrates how to create a 1-D lookup S-function (sfun_directlook.c) and
its corresponding inlined sfun_directlook.tlc file (see the Real-Time
Workshop User’s Guide and the Target Language Compiler Reference Guide for
more details on the Target Language Compiler). This 1-D direct-index lookup
table example demonstrates the following concepts that you need to know to
create your own custom lookup tables:
8-21
8 Writing S-Functions for Real-Time Workshop
S-Function RTWdata
There is a property of blocks called RTWdata, which can be used by the Target
Language Compiler when inlining an S-function. RTWdata is a structure of
strings that you can attach to a block. It is saved with the model and placed in
the model.rtw file when generating code. For example, this set of MATLAB
commands,
mydata.field1 = 'information for field1';
mydata.field2 = 'information for field2';
set_param(gcb,'RTWdata',mydata)
get_param(gcb,'RTWdata')
Inside the model.rtw for the associated S-function block is this information.
Block {
Type "S-Function"
RTWdata {
field1 "information for field1"
field2 "information for field2"
}
8-22
Fully Inlined S-Function with the mdlRTW Routine
XData and YData are double vectors of equal length representing the values of
the unknown function. XDataEvenlySpaced is a scalar, 0.0 for false and 1.0 for
true. If the XData vector is evenly spaced, then more efficient code is generated.
8-23
8 Writing S-Functions for Real-Time Workshop
1
1 1.5 2 2.5 3 3.5 4 4.5 5 5.5 6
8-24
Fully Inlined S-Function with the mdlRTW Routine
index in the XData for the current x input value when the XData is unevenly
spaced. The GetDirectLookupIndex routine is called from both the S-function
and the generated code. Here the example uses the wrapper concept for sharing
C code between Simulink MEX-files and the generated code.
If the XData is evenly spaced, then both the S-function main module and the
generated code contain the lookup algorithm (not a call to the algorithm) to
compute the y-value of a given x-value because the algorithm is short. This
demonstrates the use of a fully inlined S-function for generating optimal code.
The inlined TLC file, which performs either a wrapper call or embeds the
optimal C code, is sfun_directlook.tlc (see page 8– 39).
Error Handling
In this example, the mdlCheckParameters routine on page 8– 31 verifies that:
• The new parameter settings are correct.
• XData and YData are vectors of the same length containing real finite
numbers.
• XDataEvenlySpaced is a scalar.
• The XData vector is a monotonically increasing vector and evenly spaced if
needed.
8-25
8 Writing S-Functions for Real-Time Workshop
mdlRTW Usage
The Real-Time Workshop calls the mdlRTW routine while it (the Real-Time
Workshop) generates the model.rtw file. You can add information to the
model.rtw file about the mode in which your S-function block is operating to
produce optimal code for your Simulink model.
This example adds the following information to the model.rtw file:
Example Model
Before examining the S-function and the inlined TLC file, consider the
generated code for the following model.
8-26
Fully Inlined S-Function with the mdlRTW Routine
When creating this model, you need to specify the following for each S-function
block.
set_param(‘sfun_directlook_ex/S-Function’,’SFunctionModules’,’lookup_index’)
set_param(‘sfun_directlook_ex/S-Function1’,’SFunctionModules’,’lookup_index’)
This informs the Real-Time Workshop build process that the module
lookup_index.c is needed when creating the executable.
#include <math.h>
#include <string.h>
#include “sfun_directlook_ex.h”
#include “sfun_directlook_ex.prm”
8-27
8 Writing S-Functions for Real-Time Workshop
rtY.Out1 = rtb_buffer2;
/* Terminate function */
void MdlTerminate(void)
{
/* (no terminate code required) */
}
#include “sfun_directlook_ex.reg”
/* [EOF] sfun_directlook_ex.c */
matlabroot/simulink/src/sfun_directlook.c
/*
* File : sfun_directlook.c
* Abstract:
*
* Direct 1-D lookup. Here we are trying to compute an approximate
* solution, p(x) to an unknown function f(x) at x=x0, given data point
* pairs (x,y) in the form of a x data vector and a y data vector. For a
* given data pair (say the i’th pair), we have y_i = f(x_i). It is
* assumed that the x data values are monotonically increasing. If the
* x0 is outside of the range of the x data vector, then the first or
* last point will be returned.
*
* This function returns the “nearest” y0 point for a given x0. No
* interpolation is performed.
*
* The S-function parameters are:
* XData - double vector
* YData - double vector
8-28
Fully Inlined S-Function with the mdlRTW Routine
#include <math.h>
#include “simstruc.h”
#include <float.h>
/*=========*
* Defines *
*=========*/
#define XVECT_PIDX 0
#define YVECT_PIDX 1
#define XDATAEVENLYSPACED_PIDX 2
#define NUM_PARAMS 3
/*==============*
* misc defines *
*==============*/
#if !defined(TRUE)
#define TRUE 1
#endif
#if !defined(FALSE)
#define FALSE 0
#endif
/*===========*
* typedef’s *
*===========*/
/*===================================================================*
* Prototype define for the function in separate file lookup_index.c *
*===================================================================*/
8-29
8 Writing S-Functions for Real-Time Workshop
/*=========================*
* Local Utility Functions *
*=========================*/
return(TRUE);
} else {
return(FALSE);
}
}
/* end IsRealVect */
/*====================*
* S-function routines *
*====================*/
8-30
Fully Inlined S-Function with the mdlRTW Routine
if (!IsRealVect(XVECT(S))) {
ssSetErrorStatus(S,”1st, X-vector parameter must be a real finite “
“ vector”);
return;
}
if (!IsRealVect(YVECT(S))) {
ssSetErrorStatus(S,”2nd, Y-vector parameter must be a real finite “
“vector”);
return;
}
/*
* Verify that the dimensions of X and Y are the same.
*/
if (mxGetNumberOfElements(XVECT(S)) != mxGetNumberOfElements(YVECT(S)) ||
mxGetNumberOfElements(XVECT(S)) == 1) {
ssSetErrorStatus(S,”X and Y-vectors must be of the same dimension “
“and have at least two elements”);
return;
}
/*
* Verify we have a valid XDataEvenlySpaced parameter.
*/
if (!mxIsNumeric(XDATAEVENLYSPACED(S)) ||
!(mxIsDouble(XDATAEVENLYSPACED(S)) ||
mxIsLogical(XDATAEVENLYSPACED(S))) ||
mxIsComplex(XDATAEVENLYSPACED(S)) ||
mxGetNumberOfElements(XDATAEVENLYSPACED(S)) != 1) {
ssSetErrorStatus(S,”3rd, X-evenly-spaced parameter must be scalar “
“(0.0=false, 1.0=true)”);
return;
}
/*
* Verify x-data is correctly spaced.
*/
{
int_T i;
boolean_T spacingEqual;
real_T *xData = mxGetPr(XVECT(S));
8-31
8 Writing S-Functions for Real-Time Workshop
/*
* spacingEqual is TRUE if user XDataEvenlySpaced
*/
spacingEqual = (mxGetScalar(XDATAEVENLYSPACED(S)) != 0.0);
if (badSpacing) {
ssSetErrorStatus(S,”X-vector must be an evenly spaced “
“strictly monotonically increasing vector”);
return;
}
} else { /* XData is ‘unevenly-spaced’ */
for (i = 1; i < numEl; i++) {
if (xData[i] <= xData[i-1]) {
ssSetErrorStatus(S,”X-vector must be a strictly “
“monotonically increasing vector”);
return;
}
}
}
}
}
#endif /* MDL_CHECK_PARAMETERS */
8-32
Fully Inlined S-Function with the mdlRTW Routine
{
ssSetNumSFcnParams(S, NUM_PARAMS); /* Number of expected parameters */
/*
* Check parameters passed in, providing the correct number was specified
* in the S-function dialog box. If an incorrect number of parameters
* was specified, Simulink will detect the error since ssGetNumSFcnParams
* and ssGetSFcnParamsCount will differ.
* ssGetNumSFcnParams - This sets the number of parameters your
* S-function expects.
* ssGetSFcnParamsCount - This is the number of parameters entered by
* the user in the Simulink S-function dialog box.
*/
#if defined(MATLAB_MEX_FILE)
if (ssGetNumSFcnParams(S) == ssGetSFcnParamsCount(S)) {
mdlCheckParameters(S);
if (ssGetErrorStatus(S) != NULL) {
return;
}
} else {
return; /* Parameter mismatch will be reported by Simulink */
}
#endif
ssSetNumContStates(S, 0);
ssSetNumDiscStates(S, 0);
ssSetInputPortTestPoint(S, 0, FALSE);
ssSetInputPortOverWritable(S, 0, TRUE);
ssSetOutputPortTestPoint(S, 0, FALSE);
ssSetNumSampleTimes(S, 1);
ssSetSFcnParamNotTunable(S, XDATAEVENLYSPACED_PIDX);
ssSetOptions(S, SS_OPTION_EXCEPTION_FREE_CODE);
} /* mdlInitializeSizes */
8-33
8 Writing S-Functions for Real-Time Workshop
{
ssSetSampleTime(S, 0, INHERITED_SAMPLE_TIME);
ssSetOffsetTime(S, 0, 0.0);
} /* end mdlInitializeSampleTimes */
if (cache == NULL) {
ssSetErrorStatus(S,”memory allocation error”);
return;
}
ssSetUserData(S, cache);
if (mxGetScalar(XDATAEVENLYSPACED(S)) != 0.0){
cache->evenlySpaced = TRUE;
}else{
cache->evenlySpaced = FALSE;
}
}
#endif /* MDL_START */
8-34
Fully Inlined S-Function with the mdlRTW Routine
/*
* When the XData is evenly spaced, we use the direct lookup algorithm
* to calculate the lookup
*/
if (cache->evenlySpaced) {
real_T spacing = xData[1] - xData[0];
for (i = 0; i < ny; i++) {
real_T u = *uPtrs[i];
if (u <= xData[0]) {
y[i] = yData[0];
} else if (u >= xData[xLen-1]) {
y[i] = yData[xLen-1];
} else {
int_T idx = (int_T)((u - xData[0])/spacing);
y[i] = yData[idx];
}
}
} else {
/*
* When the XData is unevenly spaced, we use a bisection search to
* locate the lookup index.
*/
for (i = 0; i < ny; i++) {
int_T idx = GetDirectLookupIndex(xData,xLen,*uPtrs[i]);
y[i] = yData[idx];
}
}
} /* end mdlOutputs */
8-35
8 Writing S-Functions for Real-Time Workshop
* Abstract:
* This function is called when the Real-Time Workshop is generating the
* model.rtw file. In this routine, you can call the following functions
* which add fields to the model.rtw file.
*
* Important! Since this S-function has this mdlRTW routine, it must have
* a correSponding .tlc file to work with the Real-Time Workshop. You will find
* the sfun_directlook.tlc in the same directory as sfun_directlook.dll.
*/
static void mdlRTW(SimStruct *S)
{
/*
* Write out the [X,Y] data as parameters, i.e., these values can be
* changed during execution.
*/
{
real_T *xData = mxGetPr(XVECT(S));
int_T xLen = mxGetNumberOfElements(XVECT(S));
real_T *yData = mxGetPr(YVECT(S));
int_T yLen = mxGetNumberOfElements(YVECT(S));
if (!ssWriteRTWParameters(S,2,
SSWRITE_VALUE_VECT,”XData”,””,xData,xLen,
SSWRITE_VALUE_VECT,”YData”,””,yData,yLen)) {
return; /* An error occurred which will be reported by Simulink */
}
}
/*
* Write out the spacing setting as a param setting, i.e., this cannot be
* changed during execution.
*/
{
boolean_T even = (mxGetScalar(XDATAEVENLYSPACED(S)) != 0.0);
if (!ssWriteRTWParamSettings(S, 1,
SSWRITE_VALUE_QSTR,
“XSpacing”,
even ? “EvenlySpaced” : “UnEvenlySpaced”)){
return;/* An error occurred which will be reported by Simulink */
}
}
}
#endif /* MDL_RTW */
/*=============================*
* Required S-function trailer *
*=============================*/
8-36
Fully Inlined S-Function with the mdlRTW Routine
#endif
/* [EOF] sfun_directlook.c */
matlabroot/simulink/src/lookup_index.c
/* File : lookup_index.c
* Abstract:
*
* Contains a routine used by the S-function sfun_directlookup.c to
* compute the index in a vector for a given data value.
*
* Copyright (c) 1990-1998 by The MathWorks, Inc. All Rights Reserved.
* $Revision: 1.3 $
*/
#include “tmwtypes.h”
/*
* Function: GetDirectLookupIndex ==============================================
* Abstract:
* Using a bisection search to locate the lookup index when the x-vector
* isn’t evenly spaced.
*
* Inputs:
* *x : Pointer to table, x[0] ....x[xlen-1]
* xlen : Number of values in xtable
* u : input value to look up
*
* Output:
* idx : the index into the table such that:
* if u is negative
* x[idx] <= u < x[idx+1]
* else
* x[idx] < u <= x[idx+1]
*/
int_T GetDirectLookupIndex(const real_T *x, int_T xlen, real_T u)
{
int_T idx = 0;
int_T bottom = 0;
int_T top = xlen-1;
/*
* Deal with the extreme cases first:
*
* i] u <= x[bottom] then idx = bottom
* ii] u >= x[top] then idx = top-1
*
*/
if (u <= x[bottom]) {
return(bottom);
} else if (u >= x[top]) {
8-37
8 Writing S-Functions for Real-Time Workshop
return(top);
}
/*
* We have: x[bottom] < u < x[top], onward
* with search for the appropriate index ...
*/
for (;;) {
idx = (bottom + top)/2;
if (u < x[idx]) {
top = idx;
} else if (u > x[idx+1]) {
bottom = idx + 1;
} else {
/*
* We have: x[idx] <= u <= x[idx+1], only need
* to do two more checks and we have the answer.
*/
if (u < 0) {
/*
* We want right continuity, i.e.,
* if u == x[idx+1]
* then x[idx+1] <= u < x[idx+2]
* else x[idx ] <= u < x[idx+1]
*/
return( (u == x[idx+1]) ? (idx+1) : idx);
} else {
/*
* We want left continuity, i.e.,
* if u == x[idx]
* then x[idx-1] < u <= x[idx ]
* else x[idx ] < u <= x[idx+1]
*/
return( (u == x[idx]) ? (idx-1) : idx);
}
}
}
} /* end GetDirectLookupIndex */
/* [EOF] lookup_index.c */
8-38
Fully Inlined S-Function with the mdlRTW Routine
matlabroot/toolbox/simulink/blocks/tlc_c/sfun_directlook.tlc
%% File : sfun_directlook.tlc
%% Abstract:
%% Level-2 S-function sfun_directlook block target file.
%% It is using direct lookup algorithm without interpolation.
%%
%% Copyright (c) 1994-1998 by The MathWorks, Inc. All Rights Reserved.
%% $Revision: 1.3 $
%<LibCacheFunctionPrototype(buffer)>
%endfunction
8-39
8 Writing S-Functions for Real-Time Workshop
%endif
%endroll
%else
%% When the XData is unevenly spaced, we use a bisection search to
%% locate the lookup index.
int_T idx;
8-40
Fully Inlined S-Function with the mdlRTW Routine
%endif
%endroll
%endif
}
%endfunction
%% EOF: sfun_directlook.tlc
8-41
8 Writing S-Functions for Real-Time Workshop
8-42
9
S-Function
Callback Methods
Callback Method Reference . . . . . . . . . . . . . . 9-2
mdlCheckParameters . . . . . . . . . . . . . . . . . 9-3
mdlDerivatives . . . . . . . . . . . . . . . . . . . 9-5
mdlGetTimeOfNextVarHit . . . . . . . . . . . . . . . 9-6
mdlInitializeConditions . . . . . . . . . . . . . . . . 9-7
mdlInitializeSampleTimes . . . . . . . . . . . . . . . 9-9
mdlInitializeSizes . . . . . . . . . . . . . . . . . . 9-13
mdlOutputs . . . . . . . . . . . . . . . . . . . . . 9-17
mdlProcessParameters . . . . . . . . . . . . . . . . 9-18
mdlRTW . . . . . . . . . . . . . . . . . . . . . . 9-20
mdlSetDefaultPortComplexSignals . . . . . . . . . . . 9-21
mdlSetDefaultPortDataTypes . . . . . . . . . . . . . 9-22
mdlSetDefaultPortDimensionInfo . . . . . . . . . . . . 9-23
mdlSetInputPortComplexSignal . . . . . . . . . . . . 9-24
mdlSetInputPortDataType . . . . . . . . . . . . . . . 9-25
mdlSetInputPortDimensionInfo . . . . . . . . . . . . . 9-26
mdlSetInputPortFrameData . . . . . . . . . . . . . . 9-28
mdlSetInputPortSampleTime . . . . . . . . . . . . . 9-29
mdlSetInputPortWidth . . . . . . . . . . . . . . . . 9-31
mdlSetOutputPortComplexSignal . . . . . . . . . . . . 9-32
mdlSetOutputPortDataType . . . . . . . . . . . . . . 9-33
mdlSetOutputPortDimensionInfo . . . . . . . . . . . . 9-34
mdlSetOutputPortSampleTime . . . . . . . . . . . . . 9-36
mdlSetOutputPortWidth . . . . . . . . . . . . . . . 9-37
mdlSetWorkWidths . . . . . . . . . . . . . . . . . . 9-38
mdlStart . . . . . . . . . . . . . . . . . . . . . . 9-39
mdlTerminate . . . . . . . . . . . . . . . . . . . . 9-40
mdlUpdate . . . . . . . . . . . . . . . . . . . . . 9-41
mdlZeroCrossings . . . . . . . . . . . . . . . . . . 9-42
9 S-Function Callback Methods
9-2
mdlCheckParameters
Purpose 9mdlCheckParameters
Check the validity of an S-function’s parameters.
Arguments S
Simstruct representing an S-function block.
Note You cannot access the work, state, input, output, and other vectors in
this routine. Use this routine only to validate the parameters. Additional
processing of the parameters should be done in mdlProcessParameters.
Example This example checks the first S-function parameter to verify that it is a real
nonnegative scalar.
#define PARAM1(S) ssGetSFcnParam(S,0)
#define MDL_CHECK_PARAMETERS /* Change to #undef to remove function */
#if defined(MDL_CHECK_PARAMETERS) && defined(MATLAB_MEX_FILE)
static void mdlCheckParameters(SimStruct *S)
{
if (mxGetNumberOfElements(PARAM1(S)) != 1) {
ssSetErrorStatus(S,”Parameter to S-function must be a scalar”);
return;
} else if (mxGetPr(PARAM1(S))[0] < 0) {
ssSetErrorStatus(S, “Parameter to S-function must be non-negative”);
return;
}
}
#endif /* MDL_CHECK_PARAMETERS */
9-3
mdlCheckParameters
In addition to the above routine, you must add a call to this routine from
mdlInitializSizes to check parameters during initialization since
mdlCheckParameters is only called while the simulation is running. To do this,
in mdlInitializeSizes, after setting the number of parameters you expect in
your S-function by using ssSetNumSFcnParams, use this code:
static void mdlInitializeSizes(SimStruct *S)
{
ssSetNumSFcnParams(S, 1); /* Number of expected parameters */
#if defined(MATLAB_MEX_FILE)
if(ssGetNumSfcnParams(s) == ssGetSFcnParamsCount(s) {
mdlCheckParameters(S);
if(ssGetErrorStates(S) != NULL) return;
} else {
return; /* Simulink will report a mismatch error. */
}
#endif
...
}
Languages Ada, C
9-4
mdlDerivatives
Purpose 9mdlDerivatives
Compute the S-function’s derivatives.
Arguments S
Simstruct representing an S-function block.
Description Simulink invokes this optional method at each time step to compute the
derivatives of the S-function’s continuous states. This method should store the
derivatives in the S-function’s state derivatives vector. This method can use
ssGetdX to get a pointer to the derivatives vector.
Each time the mdlDerivatives routine is called, it must explicitly set the value
of all derivatives. The derivative vector does not maintain the values from the
last call to this routine. The memory allocated to the derivative vector changes
during execution.
Languages Ada, C, M
9-5
mdlGetTimeOfNextVarHit
Purpose 9mdlGetTimeOfNextVarHit
Initialize the state vectors of this S-function.
Arguments S
Simstruct representing an S-function block.
Description Simulink invokes this optional method at every major integration step to get
the time of the next sample time hit. This method should set the time of next
hit, using ssSetTNext. The time of the next hit must be greater than the
current simulation time as returned by ssGetT. The S-function must
implement this method if it operates at a discrete, variable-step sample time.
Note The time of next hit can be a function of the input signal(s).
Languages C, M
Example
static void mdlGetTimeOfNextVarHit(SimStruct *S)
{
time_T offset = getOffset();
time_T timeOfNextHit = ssGetT(S) + offset;
ssSetTNext(S, timeOfNextHit);
}
9-6
mdlInitializeConditions
Purpose 9mdlInitializeConditions
Initialize the state vectors of this S-function.
Arguments S
Simstruct representing an S-function block.
Example This example is an S-function with both continuous and discrete states; it
initializes both sets of states to 1.0:
#define MDL_INITIALIZE_CONDITIONS /* Change to #undef to remove function */
#if defined(MDL_INITIALIZE_CONDITIONS)
}
#endif /* MDL_INITIALIZE_CONDITIONS */
For another example which initializes only the continuous states, see
matlabroot/simulink/src/resetint.c.
9-7
mdlInitializeConditions
Languages C
9-8
mdlInitializeSampleTimes
Purpose 9mdlInitializeSampleTimes
Specify the sample rates at which this S-function operates.
Arguments S
Simstruct representing an S-function block.
Description This method should specify the sample time and offset time for each sample
rate at which this S-function operates via the following paired macros
ssSetSampleTime(S, sampleTimeIndex, sample_time)
ssSetOffsetTime(S, offsetTimeIndex, offset_time)
where sampleTimeIndex runs from 0 to one less than the number of sample
times specified in mdlInitializeSizes via ssSetNumSampleTimes.
If the S-function operates at one or more sample rates, this method can specify
any of the following sample time and offset values for a given sample time:
• [CONTINUOUS_SAMPLE_TIME, 0.0]
• [CONTINUOUS_SAMPLE_TIME, FIXED_IN_MINOR_STEP_OFFSET]
• [discrete_sample_period, offset]
• [VARIABLE_SAMPLE_TIME, 0.0]
The upper case values are macros defined in simstruc.h.
If the S-function operates at one rate, this method can alternatively set the
sample time to one of the following sample/offset time pairs.
• [INHERITED_SAMPLE_TIME, 0.0]
• [INHERITED_SAMPLE_TIME, FIXED_IN_MINOR_STEP_OFFSET]
9-9
mdlInitializeSampleTimes
9-10
mdlInitializeSampleTimes
If this function has no intrinsic sample time, it should set its sample time to
inherited according to the following guidelines:
• A function that changes as its input changes, even during minor integration
steps, should set its sample time to
[INHERITED_SAMPLE_TIME, 0.0]
A function that changes as its input changes, but doesn’t change during
minor integration steps (i.e., held during minor steps) should set its sample
time to
[INHERITED_SAMPLE_TIME, FIXED_IN_MINOR_STEP_OFFSET]
9-11
mdlInitializeSampleTimes
If the function wanted to determine if the third (discrete) task has a hit, it could
use the following code-fragment.
if (ssIsSampleHit(S,2,tid) {
}
Languages C
9-12
mdlInitializeSizes
Purpose 9mdlInitializeSizes
Specify the number of inputs, outputs, states, parameters, and other
characteristics of the S-function.
Arguments S
Simstruct representing an S-function block.
Description This is the first of the S-function’s callback methods that Simulink calls. This
method should perform the following tasks:
9-13
mdlInitializeSizes
9-14
mdlInitializeSizes
Languages Ada, C, M
Example
static void mdlInitializeSizes(SimStruct *S)
{
int_T nInputPorts = 1; /* number of input ports */
int_T nOutputPorts = 1; /* number of output ports */
int_T needsInput = 1; /* direct feed through */
int_T inputPortIdx = 0;
int_T outputPortIdx = 0;
if (ssGetErrorStatus(s) != NULL)
return;
}
ssSetNumContStates( S, 0);
ssSetNumDiscStates( S, 0);
/*
* Configure the input ports. First set the number of input
* ports.
*/
if (!ssSetNumInputPorts(S, nInputPorts)) return;
/*
* Set input port dimensions for each input port index
9-15
mdlInitializeSizes
* starting at 0.
*/
if(!ssSetInputPortDimensionInfo(S, inputPortIdx,
DYNAMIC_DIMENSION)) return;
/*
* Set direct feedthrough flag (1=yes, 0=no).
*/
ssSetInputPortDirectFeedThrough(S, inputPortIdx, needsInput);
/*
* Configure the output ports. First set the number of
* output ports.
*/
if (!ssSetNumOutputPorts(S, nOutputPorts)) return;
/*
* Set output port dimensions for each output port index
* starting at 0.
*/
if(!ssSetOutputPortDimensionInfo(S,outputPortIdx,
DYNAMIC_DIMENSION)) return;
/*
* Set the number of sample times. */
ssSetNumSampleTimes(S, 1);
/*
* Set size of the work vectors.
*/
ssSetNumRWork(S, 0); /* real vector */
ssSetNumIWork(S, 0); /* integer vector */
ssSetNumPWork(S, 0); /* pointer vector */
ssSetNumModes(S, 0); /* mode vector */
ssSetNumNonsampledZCs(S, 0); /* zero crossings */
ssSetOptions(S, 0);
} /* end mdlInitializeSizes */
9-16
mdlOutputs
Purpose 9mdlOutputs
Compute the signals that this block emits.
Arguments S
Simstruct representing an S-function block.
tid
Task id
Description Simulink invokes this required method at each simulation time step. The
method should compute the S-function’s outputs at the current time step and
store the results in the S-function’s output signal arrays.
The tid (task ID) argument specifies the task running when the mdlOutputs
routine is invoked. You can use this argument in the mdlOutports routine of a
multirate S-Function block to encapsulate task-specific blocks of code (see
“Multirate S-Function Blocks” on page 7-21).
For an example of an mdlOutputs routine that works with multiple input and
output ports, see matlabroot/simulink/src/sfun_multiport.c.
Languages A, C, M
9-17
mdlProcessParameters
Purpose 9mdlProcessParameters
Process the S-function’s parameters.
Arguments S
Simstruct representing an S-function block.
9-18
mdlProcessParameters
}
if (mxGetString(SIGNS_PARAM(S),plusMinusStr,nInputPorts+1) != 0) {
free(plusMinusStr);
ssSetErrorStatus(S,"mxGetString error in mdlStart");
return;
}
for (i = 0; i < nInputPorts; i++) {
iwork[i] = plusMinusStr[i] == '+'? 1: -1;
}
free(plusMinusStr);
}
#endif /* MDL_PROCESS_PARAMETERS */
Languages Ada, C, M
9-19
mdlRTW
Purpose 9mdlRTW
Generate code generation data.
Arguments S
Simstruct representing an S-function block.
Description This function is called when the Real-Time Workshop is generating the
model.rtw file. In this method, you can call the following functions which add
fields to the model.rtw file:
• ssWriteRTWParameters
• ssWriteRTWParamSettings
• ssWriteRTWWorkVect
• ssWriteRTWStr
• ssWriteRTWStrParam
• ssWriteRTWScalarParam
• ssWriteRTWStrVectParam
• ssWriteRTWVectParam
• ssWriteRTW2dMatParam
• ssWriteRTWMxVectParam
• ssWriteRTWMx2dMatParam
Languages C
9-20
mdlSetDefaultPortComplexSignals
Purpose 9mdlSetDefaultPortComplexSignals
Set the numeric type (real, complex, or inherited) of ports whose numeric type
cannot be determined from block connectivity.
Arguments S
Simstruct representing an S-function block.
Description Simulink invokes this method if the block has ports whose numeric type cannot
be determined from connectivity. (This usually happens when the block is
unconnected or is part of a feedback loop.) This method must set the data type
of all ports whose data type is not set.
If the block does not implement this method and Simulink cannot determine
the data types of any of its ports, Simulink sets the data types of all the ports
to double. If the block does not implement this method and Simulink cannot
determine the data types of some, but not all, of its ports, Simulink sets the
unknown ports to the data type of the port whose data type has the largest size.
Languages C
9-21
mdlSetDefaultPortDataTypes
Purpose 9mdlSetDefaultPortDataTypes
Set the data type of ports whose data type cannot be determined from block
connectivity.
Arguments S
Simstruct representing an S-function block.
Description Simulink invokes this method if the block has ports whose numeric type cannot
be determined from connectivity. (This usually happens when the block is
unconnected or is part of a feedback loop.) This method must set the numeric
type of all ports whose numeric type is not set.
If the block does not implement this method and at least one port is known to
be complex, Simulink sets the unknown ports to COMPLEX_YES; otherwise, it
sets the unknown ports to COMPLEX_NO.
Languages C
9-22
mdlSetDefaultPortDimensionInfo
Purpose 9mdlSetDefaultPortDimensionInfo
Set the default dimensions of the signals accepted or emitted by an S-function’s
ports.
Arguments S
Simstruct representing an S-function block.
Description Simulink calls this method during signal dimension propagation when a model
does not supply enough information to determine the dimensionality of signals
that can enter or leave the block represented by S. This method should set the
dimensions of any input and output ports that are dynamically sized to default
values. If S does not implement this method, Simulink set the dimensions of
dynamically sized ports for which dimension information is unavailable to
scalar, i.e., 1-D signals containing one element.
Languages C
9-23
mdlSetInputPortComplexSignal
Purpose 9mdlSetInputPortComplexSignal
Set the numeric type (real, complex, or inherited) of the signals accepted by an
input port.
Arguments S
Simstruct representing an S-function block.
port
Index of a port
csig
Numeric type of signal
Description Simulink calls this routine to set the input port signal type. The S-function
must check if the specified signal type is a valid type for the specified port. If it
is valid, the s-function must set the signal type of the specified input port.
Otherwise, it must report an error using ssSetErrorStatus. The s-function
can also set the signal type of other input and output ports with unknown
signal types. Simulink reports an error if the S-function changes the signal
type of a port whose signal type is known.
If the S-function does not implement this routine, Simulink assumes that the
S-function accepts a real or complex signal and sets the input port signal type
to the specified value.
Languages C
9-24
mdlSetInputPortDataType
Purpose 9mdlSetInputPortDataType
Set the data type of the signals accepted by an input port.
Arguments S
Simstruct representing an S-function block.
port
Index of a port
id
Data type id
Description Simulink calls this routine to set the data type of port. The S-function must
check if the specified data type is a valid data type for the specified port. If it is
a valid data type, it must set the data type of the input port. Otherwise, it must
report an error using ssSetErrorStatus.
The S-function can also set the data type of other input and output ports if they
are unknown. Simulink reports an error if the S-function changes the data type
of a port whose data type has been set.
If the block does not implement this routine, Simulink assumes that the block
accepts any data type and sets the input port data type to the specified value.
Languages C
9-25
mdlSetInputPortDimensionInfo
Purpose 9mdlSetInputPortDimensionInfo
Set the dimensions of the signals accepted by an input port.
Arguments S
Simstruct representing an S-function block.
port
Index of a port
dimsInfo
Structure that specifies the signal dimensions supported by port
See ssSetInputPortDimensionInfo for a description of this structure.
Description Simulink calls this method during dimension propagation with candidate
dimensions, dimsInfo, for port. If the proposed dimensions are acceptable, this
method should go ahead and set the actual port dimensions, using
ssSetInputPortDimensionInfo. If they are unacceptable, this method should
generate an error via ssSetErrorStatus.
Note This method can set the dimensions of any other input or output port
whose dimensions derive from the dimensions of port.
By default, Simulink calls this method only if it can fully determine the
dimensionality of port from the port to which it is connected. If it cannot
completely determine the dimensionality from port connectivity, it invokes
mdlSetDefaultPortDimensionInfo. If an S-function can fully determine the
port dimensionality from partial information, the function should set the
option, SS_OPTION_ALLOW_PARTIAL_DIMENSIONS_CALL, in
mdlInitializeSizes, using ssSetOptions. If this option is set, Simulink
invokes mdlSetInputPortDimensionInfo even if it can only partially
determine the dimensionality of the input port from connectivity.
Languages C
9-26
mdlSetInputPortDimensionInfo
9-27
mdlSetInputPortFrameData
Purpose 9mdlSetInputPortFrameData
Set frame data entering an input port.
Arguments S
Simstruct representing an S-function block.
port
Index of a port
frameData
frame data
Description This method is called with the candidate frame setting (FRAME_YES, or
FRAME_NO) for an input port. If the proposed setting is acceptable, the method
should go ahead and set the actual frame data setting using
ssSetInputPortFrameData. If the setting is unacceptable an error should
generated via ssSetErrorStatus. Note that any other dynamic frame input or
output ports whose frame data setting are implicitly defined by virtue of
knowing the frame data setting of the given port can also have their frame data
settings set via calls to ssSetInputPortFrameData and
ssSetOutputPortFrameData.
Languages C
9-28
mdlSetInputPortSampleTime
Purpose 9mdlSetInputPortSampleTime
Set the sample time of an input port that inherits its sample time from the port
to which it is connected.
Arguments S
Simstruct representing an S-function block.
port
Index of a port
sampleTime
Inherited sample time for port
offsetTime
Inherited offset time for port
Description Simulink invokes this method with the sample time that port inherits from the
port to which it is connected. If the inherited sample time is acceptable, this
method should set the sample time of port to the inherited time, using
ssSetInputPortSampleTime. If the sample time is unacceptable, this method
should generate an error via ssSetErrorStatus. Note that any other inherited
input or output ports whose sample times are implicitly defined by virtue of
knowing the sample time of the given port can also have their sample times set
via calls to ssSetInputPortSampleTime or ssSetOutputPortSampleTime.
When inherited port based sample times are specified, we are guaranteed that
the sample time will be one of the following:.
where 0.0 < period < inf and 0.0 <= offset < period. Constant, triggered,
and variable step sample times are not be propagated to S-functions with port-
based sample times.
9-29
mdlSetInputPortSampleTime
The final sample time specified at the port may be different from (but
equivalent to) the sample time specified by this method. This occurs when:
• The model uses a fixed step solver and the port has a continuous but fixed in
minor step sample time. In this case, Simulink converts the sample time to
the fundamental sample time for the model.
• Simulink adjusts the sample time to be as numerically sound as possible. For
example, Simulink converts [0.2499999999999, 0] to [0.25, 0].
Languages C
9-30
mdlSetInputPortWidth
Purpose 9mdlSetInputPortWidth
Set the width of an input port that accepts 1-D (vector) signals.
Arguments S
Simstruct representing an S-function block.
port
Index of a port
width
Width of signal
Description This method is called with the candidate width for a dynamically sized port. If
the proposed width is acceptable, the method should go ahead and set the
actual port width using ssSetInputPortWidth. If the size is unacceptable an
error should generated via ssSetErrorStatus. Note that any other
dynamically sized input or output ports whose widths are implicitly defined by
virtue of knowing the width of the given port can also have their widths set via
calls to ssSetInputPortWidth or ssSetOutputPortWidth.
Languages C
9-31
mdlSetOutputPortComplexSignal
Purpose 9mdlSetOutputPortComplexSignal
Set the numeric type (real, complex, or inherited) of the signals accepted by an
output port.
Arguments S
Simstruct representing an S-function block.
port
Index of a port
csig
Numeric type of signal
Description Simulink calls this routine to set the output port signal type. The S-function
must check if the specified signal type is a valid type for the specified port. If it
is valid, the s-function must set the signal type of the specified output port.
Otherwise, it must report an error using ssSetErrorStatus. The s-function
can also set the signal type of other input and output ports with unknown
signal types. Simulink reports an error if the S-function changes the signal
type of a port whose signal type is known.
If the S-function does not implement this routine, Simulink assumes that the
S-function accepts a real or complex signal and sets the output port signal type
to the specified value.
Languages C
9-32
mdlSetOutputPortDataType
Purpose 9mdlSetOutputPortDataType
Set the data type of the signals emitted by an output port.
Arguments S
Simstruct representing an S-function block.
port
Index of an output port
id
Data type id
Description Simulink calls this routine to set the data type of port. The S-function must
check if the specified data type is a valid data type for the specified port. If it is
a valid data type, it must set the data type of port. Otherwise, it must report
an error using ssSetErrorStatus.
The S-function can also set the data type of other input and output ports if their
data types have not been set. Simulink reports an error if the S-function
changes the data type of a port whose data type has been set.
If the block does not implement this method, Simulink assumes that the block
accepts any data type and sets the input port data type to the specified value.
Languages C
9-33
mdlSetOutputPortDimensionInfo
Purpose 9mdlSetOutputPortDimensionInfo
Set the dimensions of the signals accepted by an output port.
Arguments S
Simstruct representing an S-function block or a Simulink model.
port
Index of a port
dimsInfo
Structure that specifies the signal dimensions supported by port
See ssSetInputPortDimensionInfo for a description of this structure.
Description Simulink calls this method with candidate dimensions, dimsInfo, for port. If
the proposed dimensions are acceptable, this method should go ahead and set
the actual port dimensions, using ssSetOutputPortDimensionInfo. If they are
unacceptable, this method should generate an error via ssSetErrorStatus.
Note This method can set the dimensions of any other input or output port
whose dimensions derive from the dimensions of port.
By default, Simulink calls this method only if it can fully determine the
dimensionality of port from the port to which it is connected. If it cannot
completely determine the dimensionality from port connectivity, it invokes
mdlSetDefaultPortDimensionInfo. If an S-function can fully determine the
port dimensionality from partial information, the function should set the
option, SS_OPTION_ALLOW_PARTIAL_DIMENSIONS_CALL, in
mdlInitializeSizes, using ssSetOptions. If this option is set, Simulink
invokes mdlSetOutputPortDimensionInfo even if it can only partially
determine the dimensionality of the input port from connectivity.
Languages C
9-34
mdlSetOutputPortDimensionInfo
9-35
mdlSetOutputPortSampleTime
Purpose 9mdlSetOutputPortSampleTime
Set the sample time of an output port that inherits its sample time from the
port to which it is connected.
Arguments S
Simstruct representing an S-function block.
port
Index of a port
sampleTime
Inherited sample time for port
offsetTime
Inherited offset time for port
Description Simulink calls this method with the sample time that port inherits from the
port to which it is connected. If the inherited sample time is acceptable, this
method should set the sample time of port to the inherited sample time, using
ssSetOutputPortSampleTime. If the inherited sample time is unacceptable,
this method should generate an error generated via ssSetErrorStatus. Note
that this method can set the sample time of any other input or output port
whose sample time derives from the sample time of port, using
ssSetInputPortSampleTime or ssSetOutputPortSampleTime.
Languages C
9-36
mdlSetOutputPortWidth
Purpose 9mdlSetOutputPortWidth
Set the width of an output port that outputs 1-D (vector) signals.
Arguments S
Simstruct representing an S-function block.
port
Index of a port
width
Width of signal
Description This method is called with the candidate width for a dynamically sized port. If
the proposed width is acceptable, the method should go ahead and set the
actual port width using ssSetOutputPortWidth. If the size is unacceptable an
error should generated via ssSetErrorStatus. Note that any other
dynamically sized input or output ports whose widths are implicitly defined by
virtue of knowing the width of the given port can also have their widths set via
calls to ssSetInputPortWidth or ssSetOutputPortWidth.
Languages C
9-37
mdlSetWorkWidths
Purpose 9mdlSetWorkWidths
Specify the sizes of the work vectors and create the runtime parameters
required by this S-function.
Arguments S
Simstruct representing an S-function block.
Description Simulink calls this optional method to enable this S-function to set the sizes of
state and work vectors that it needs to store global data and to create runtime
parameters (see “Run-Time Parameters” on page 7-6). Simulink invokes this
method after it has determined the input port width, output port width, and
sample times of the S-function. This allows the S-function to size the state and
work vectors based on the number and sizes of inputs and outputs and/or the
number of sample times. This method specify the state and work vector sizes
via the macros ssNumContStates, ssSetNumDiscStates, ssSetNumRWork,
ssSetNumIWork, ssSetNumPWork, ssSetNumModes, and
ssSetNumNonsampledZCs.
The S-function needs to implement this method only if it does not know the
sizes of all the work vectors it requires when Simulink invokes the function’s
mdlInitializeSizes method. If this S-function implements
mdlSetWorkWidths, it should initialize the sizes of any work vectors that it
needs to DYNAMICALLY_SIZED in mdlIntializeSizes, even for those whose
exact size it knows at that point. The S-function should then specify the actual
size in mdlSetWorkWidths.
Languages Ada, C
9-38
mdlStart
Purpose 9mdlStart
Initialize the state vectors of this S-function.
Arguments S
Simstruct representing an S-function block.
Languages Ada, C
9-39
mdlTerminate
Purpose 9mdlTerminate
Perform any actions required at termination of the simulation.
Arguments S
Simstruct representing an S-function block.
Description This method should perform any actions, such as freeing memory, that must be
performed at the end of simulation or when an S-function block is destroyed
(e.g., when it is deleted from a model). The option
SS_OPTION_CALL_TERMINATE_ON_EXIT (see ssSetOptions) determines
whether Simulink invokes this method. If this option is not set, Simulink
invokes mdlTerminate at the end of simulation only if the mdlStart method of
at least one block in the model has executed during simulation. If this option is
set, Simulink always invokes the mdlTerminate method at the end of a
simulation run and whenever it destroys a block.
Languages Ada, C, M
Example Suppose your S-function allocates blocks of memory in mdlStart and saves
pointers to the blocks in a PWork vector. The following code fragment would free
this memory.
{
int i;
for (i = 0; i<ssGetNumPWork(S); i++) {
if (ssGetPWorkValue(S,i) != NULL) {
free(ssGetPWorkValue(S,i));
}
}
}
9-40
mdlUpdate
Purpose 9mdlUpdate
Update a block’s states.
Arguments S
Simstruct representing an S-function block.
tid
Task ID
Description Simulink invokes this optional method at each major simulation time step. The
method should compute the S-function’s states at the current time step and
store the states in the S-function’s state vector. The method can also perform
any other tasks that the S-function needs to perform at each major time step.
Use this code if your S-function has one or more discrete states or does not have
direct feedthrough.
The reason for this is that most S-functions that do not have discrete states but
do have direct feedthrough do not have update functions. Therefore, Simulink
is able to eliminate the need for the extra call in these circumstances.
If your S-function needs to have its mdlUpdate routine called and it does not
satisfy either of the above two conditions, specify that it has a discrete state
using the ssSetNumDiscStates macro in the mdlInitializeSizes function.
The tid (task ID) argument specifies the task running when the mdlOutputs
routine is invoked. You can use this argument in the mdlUpdate routine of a
multirate S-Function block to encapsulate task-specific blocks of code (see
“Multirate S-Function Blocks” on page 7-21).
Languages Ada, C, M
9-41
mdlZeroCrossings
Purpose 9mdlZeroCrossings
Update zero-crossing vector.
Arguments S
Simstruct representing an S-function block.
Description An S-function needs to provide this optional method only if it does zero-crossing
detection. This method should update the S-function’s zero-crossing vector,
using ssGetNonsampleZCs.
You can use the optional mdlZeroCrossings routine, when your S-function has
registered the CONTINUOUS_SAMPLE_TIME and has nonsampled zero crossings
(ssGetNumNonsampledZCs(S) > 0). The mdlZeroCrossings routine is used to
provide Simulink with signals that are to be tracked for zero crossings. These
are typically:
Thus, the zero crossing signals are used to locate the discontinuities and end
the current time step at the point of the zero crossing. To provide Simulink with
zero crossing signal(s), mdlZeroCrossings updates the ssGetNonsampleZCs(S)
vector.
Languages C
9-42
10
SimStruct Functions
Introduction . . . . . . . . . . . . . . . . . . . . 10-2
Language Support . . . . . . . . . . . . . . . . . . 10-2
The SimStruct . . . . . . . . . . . . . . . . . . . . 10-2
Introduction
Simulink provides a set of functions for accessing the fields of an S-function’s
simulation data structure (SimStruct). S-function callback methods use these
functions to store and retrieve information about an S-function.
This reference describes the syntax and usage of each SimStruct function. The
descriptions appear alphabetically by name to facilitate location of a particular
macro. This section also provides listings of functions by usage to speed
location of macros for specific purposes, such as implementing data type
support.
Language Support
Some SimStruct functions are available only in some of the languages
supported by Simulink.The reference page for each SimStruct function lists the
languages in which it is available. If the SimStruct function is available in C,
the reference page gives its C syntax. Otherwise, it gives its syntax in the
language in which it is available.
The SimStruct
The file matlabroot/simulink/include/simstruc.h is a C language header
file that defines the Simulink data structure and the SimStruct access macros.
It encapsulates all the data relating to the model or S-function, including block
parameters and outputs.
There is one SimStruct data structure allocated for the Simulink model. Each
S-function in the model has its own SimStruct associated with it. The
organization of these SimStructs is much like a directory tree. The SimStruct
associated with the model is the root SimStruct. The SimStructs associated
with the S-functions are the child SimStructs.
10-2
SimStruct Macros and Functions Listed by Usage
Miscellaneous
Macro Description
Macros Description
10-3
10 SimStruct Functions
Macros Description
I/O Port
Macro Description
10-4
SimStruct Macros and Functions Listed by Usage
Macro Description
10-5
10 SimStruct Functions
Macro Description
Macro Description
10-6
SimStruct Macros and Functions Listed by Usage
Macro Description
Run-Time Parameters
These macros allow you to create, update, and access run-time parameters
corresponding to a block’s dialog parameters.
Macro Description
10-7
10 SimStruct Functions
Sample Time
Macro Description
10-8
SimStruct Macros and Functions Listed by Usage
Macro Description
10-9
10 SimStruct Functions
Macro Description
10-10
SimStruct Macros and Functions Listed by Usage
Macro Description
10-11
10 SimStruct Functions
Simulation Information
Macro Description
Function Call
Macro Description
10-12
SimStruct Macros and Functions Listed by Usage
Data Type
Macro Description
Real-Time Workshop
Macro Description
10-13
10 SimStruct Functions
Macro Description
10-14
Macro Reference
Macro Reference
This section contains descriptions of each SimStruct macro.
10-15
ssCallExternalModeFcn
Purpose 10ssCallExternalModeFcn
Invoke the external mode function for an S-function.
Arguments S
SimStruct representing an S-function block or a Simulink model.
fcn
external mode function
Languages C
10-16
ssCallSystemWithTid
Purpose 10ssCallSystemWithTid
Specify that an output port is issuing a function call.
Arguments S
SimStruct representing an S-function block or a Simulink model.
port_index
Index of port that is issuing the function call
tid
Task ID.
Languages C
10-17
ssGetAbsTol
Purpose 10ssGetAbsTol
Get the absolute tolerances used by the model’s variable step solver.
Arguments S
SimStruct representing an S-function block.
Description Use in mdlStart to get the absolute tolerances used by the variable step solver
for this simulation. Returns a pointer to an array that contains the tolerance
for each continuous state.
Note Absolute tolerances are not allocated for fixed step solvers. Therefore,
you should not invoke this macro until you have verified that the simulation is
using a variable step solver, using ssIsVariableStepSolver.
Languages C, C++
Example {
int isVarSolver = ssIsVariableStepSolver(S);
if (isVarSolver) {
real_T *absTol = ssGetAbsTol(S);
int nCStates = ssGetNumContStates(S);
absTol[0] = whatever_value;
...
absTol[nCStates-1] = whatever_value;
}
}
10-18
ssGetBlockReduction
Purpose 10ssGetBlockReduction
Determine whether a block has requested block reduction before the
simulation has begun and whether it has actually been reduced after the
simulation loop has begun.
Arguments S
SimStruct representing an S-function block
Description The result of this function depends on when it is invoked. When invoked before
the simulation loop has started, i.e., in mdlSetWorkWidths or earlier, this
macro returns TRUE if the block has previously requested that it be reduced.
When invoked after the simulation loop has begun, this macro returns TRUE
if the block has actually been reduced, i.e., eliminated from the list of blocks to
be executed during the simulation loop.
Note If a block has been reduced, the only callback method invoked for the
block after the simulation loop has begun is the block’s mdlTerminate method.
Further, Simulink invokes the mdlTerminate method only if the block has set
its SS_OPTION_CALL_TERMINATE_AT_EXIT option, using ssSetOption. Thus, if
your block needs to determine whether it has actually been reduced, it must
set the SS_OPTION_CALL_TERMINATE_AT_EXIT option before the simulation
loop has begun and invoke ssGetBlockReduction in its mdlTerminate
method.
Languages C
10-19
ssGetContStateAddress
Purpose 10ssGetContStateAddress
Get the address of a block’s continuous states.
Arguments S
SimStruct representing an S-function block.
Languages Ada
10-20
ssGetContStates
Purpose 10ssGetContStates
Get a block’s continuous states.
Arguments S
SimStruct representing an S-function block.
Languages C
10-21
ssGetDataTypeName
Purpose 10ssGetDataTypeName
Get the name of a data type.
Arguments S
SimStruct representing an S-function block.
id
ID of data type
Description Returns the name of the data type specified by id, if id is valid. Otherwise, this
macro returns NULL and reports an error. Because this macro reports any error
that occurs, you do not need to use ssSetErrorStatus to report the error.
Example The following example gets the name of a custom data type.
const char *dtypeName = ssGetDataName(S, id);
if(dtypeName == NULL) return;
Languages C
10-22
ssGetDataTypeId
Purpose 10ssGetDataTypeId
Get the id of a data type.
Arguments S
SimStruct representing an S-function block.
name
Name of data type
Description Returns the id of the data type specified by name, if name is a registered type
name. Otherwise, this macro returns INVALID_DTYPE_IDL and reports an
error. Because this macro reports any error that occurs, you do not need to use
ssSetErrorStatus to report the error.
Languages C
Example The following example gets the id of the data type named Color.
int_T id = ssGetDataTypeId (S, “Color”);
if(id == INVALID_DTYPE_ID) return;
10-23
ssGetDataTypeSize
Purpose 10ssGetDataTypeSize
Get the size of a custom data type.
Arguments S
SimStruct representing an S-function block.
id
ID of data type
Description Returns the size of the data type specified by id, if id is valid and the data types
size has been set. Otherwise, this macro returns INVALID_DTYPE_SIZE and
reports an error.
Note Because this macro reports any error that occurs when it is invoked,
you do not need to use ssSetErrorStatus to report the error.
Languages C
Example The following example gets the size of the int16 data type.
int_T size = ssGetDataTypeSize(S, SS_INT16);
if(size == INVALID_DTYPE_SIZE) return;
10-24
ssGetDataTypeZero
Purpose 10ssGetDataTypeZero
Get the zero representation of a data type.
Arguments S
SimStruct representing an S-function block.
id
ID of data type
Description Returns a pointer to the zero representation of the data type specified by id, if
id is valid and the data type’s size has been set. Otherwise, this macro returns
NULL and reports an error. Because this macro reports any error that occurs,
you do not need to use ssSetErrorStatus to report the error.
Languages C
Example The following example gets the zero representation of a custom data type.
const void *myZero = ssGetDataTypeZero(S, id);
if(myZero == NULL) return;
10-25
ssGetDiscStates
Purpose 10ssGetDiscStates
Get a block’s discrete states.
Arguments S
SimStruct representing an S-function block.
Description Returns a block’s discrete state vector has an array of real_T elements of
length ssGetNumDiscStates(S). Typically, the state vector is initialized in
mdlInitializeConditions, updated in mdlUpdate, and used in mdlOutputs.
You can use this macro in the simulation loop, mdlInitializeConditions, or
mdlStart routines.
Languages C
10-26
ssGetDTypeIdFromMxArray
Purpose 10ssGetDTypeIdFromMxArray
Get the data type of an S-function parameter.
Arguments m
MATLAB array representing the parameter
10-27
ssGetDTypeIdFromMxArray
Languages C
10-28
ssGetDWork
Purpose 10ssGetDWork
Get a DWork vector.
Arguments S
SimStruct representing an S-function block.
vector
Index of a data type work vector, where the index is one of 0, 1, 2, ...
ssGetNumDWork(S)
Languages C, C++
10-29
ssGetDWorkComplexSignal
Purpose 10ssGetDWorkComplexSignal
Determine whether the elements of a data type work vector are real or complex
numbers.
Arguments S
SimStruct representing an S-function block.
vector
Index of a data type work vector, where the index is one of 0, 1, 2, ...
ssGetNumDWork(S)
Languages C, C++
10-30
ssGetDWorkDataType
Purpose 10ssGetDWorkDataType
Get the data type of a data type work vector.
Arguments S
SimStruct representing an S-function block.
vector
Index of a data type work vector, where the index is one of 0, 1, 2, ...
ssGetNumDWork(S)
Description Returns the data type of the specified data type work vectoer.
Languages C, C++
10-31
ssGetDWorkName
Purpose 10ssGetDWorkName
Get the name of a data type work vector.
Arguments S
SimStruct representing an S-function block.
name
Index of the work vector, where the index is one of 0, 1, 2, ...
ssGetNumDWork(S)
Description Returns the name of the specified data type work vector.
Languages C, C++
10-32
ssGetDWorkUsedAsDState
Purpose 10ssGetDWorkUsedAsDState
Determine whether a data type work vector is used as a discrete state vector.
Arguments S
SimStruct representing an S-function block.
vector
Index of a data type work vector, where the index is one of 0, 1, 2, ...
ssGetNumDWork(S)
Languages C, C++
10-33
ssGetDWorkWidth
Purpose 10ssGetDWorkWidth
Get the size of a data type work vector.
Arguments S
SimStruct representing an S-function block.
vector
Index of a work vector, where the index is one of 0, 1, 2, ... ssGetNumDWork(S)
Languages C, C++
10-34
ssGetdX
Purpose 10ssGetdX
Get the derivatives of a block’s continuous states.
Arguments S
SimStruct representing an S-function block.
Languages C
10-35
ssGetErrorStatus
Purpose 10ssGetErrorStatus
Get a string that identifies the last error.
Arguments S
SimStruct representing an S-function block.
Languages Ada, C
10-36
ssGetInputPortBufferDstPort
Purpose 10ssGetInputPortBufferDstPort
Determine the output port that is sharing this input port’s buffer.
Arguments S
SimStruct representing an S-function block.
inputPortIdx
Index of port overwritten by an output port.
Description Use in any run-time S-function callback routine to determine the output port
that is overwriting the specified input port. This can be used when you have
specified the following:
• The input port and some output port on an S-Function are not test points
(ssSetInputPortTestPoint and ssSetOutputPortTestPoint)
• The input port is overwritable (ssSetInputPortOverWritable)
If you have this set of conditions, Simulink may use the same memory buffer
for an input port and an output port. Simulink determines which ports share
memory buffers. Use this function any time after model initialization to get the
index of the output port that reuses the specified input port’s buffer. If none of
the S-function’s output ports reuse this input port buffer, this macro returns
INVALID_PORT_IDX (= -1).
Languages C
10-37
ssGetInputPortConnected
Purpose 10ssGetInputPortConnected
Determine whether a port is connected to a nonvirtual block.
Arguments S
SimStruct representing an S-function block or a Simulink model.
port
Port whose connection status is needed.
Description Returns true if the specified port on the block represented by S is connected to
a nonvirtual block. Can be invoked anywhere except in mdlInitializeSizes or
mdlCheckParameters. The S-function must have previously set the number of
input ports in mdlInitializeSizes, using ssSetNumInputPorts.
Languages C
10-38
ssGetInputPortComplexSignal
Purpose 10ssGetInputPortComplexSignal
Get the numeric type (complex or real) of an input port.
Arguments S
SimStruct representing an S-function block.
port
Index of an input port
Languages C
10-39
ssGetInputPortDataType
Purpose 10ssGetInputPortDataType
Get the data type of an input port.
Arguments S
SimStruct representing an S-function block or a Simulink model.
port
Index of an input port
Description Returns the data type of the input port specified by port.
Languages Ada, C
10-40
ssGetInputPortDimensionInfo
Purpose 10ssGetInputPortDimensionInfo
Specify information about the dimensionality of an input port.
Arguments S
SimStruct representing an S-function block.
port
Index of an input port
Languages C, C++
10-41
ssGetInputPortDimensions
Purpose 10ssGetInputPortDimensions
Get the dimensions of the signal accepted by an input port.
Arguments S
SimStruct representing an S-function block.
port
Index of an input port
Description Returns an array of integers that specifies the dimensions of the signal
accepted by port, e.g., [4 2] for a 4-by-2 matrix array. The size of the
dimensions array is equal to the number of signal dimensions accepted by the
port, e.g., 1 for a vector signal or 2 for a matrix signal.
Languages C
10-42
ssGetInputPortDirectFeedThrough
Purpose 10ssGetInputPortDirectFeedThrough
Determine whether a port has direct feedthrough.
Arguments S
SimStruct representing an S-function block.
port
Index of port whose direct feedthrough property is required.
Languages Ada, C
10-43
ssGetInputPortFrameData
Purpose 10ssGetInputPortFrameData
Determine if a port accepts signal frames.
Arguments S
SimStruct representing an S-function block.
port
Index of an input port
• -1
Port accepts either frame or unframed input.
•0
Port accepts unframed input only.
•1
Port accepts frame input only.
Languages C
10-44
ssGetInputPortNumDimensions
Purpose 10ssGetInputPortNumDimensions
Get the dimensionality of the signals accepted by an input port.
Arguments S
SimStruct representing an S-function block.
port
Index of an input port
Languages C
10-45
ssGetInputPortOffsetTime
Purpose 10ssGetInputPortOffsetTime
Get the offset time of an input port.
Arguments S
SimStruct representing an S-function block.
inputPortIdx
Index of port whose offset time is required.
Description Use in any routine (except mdlInitializeSizes) to determine the offset time
of an input port. This should only be used if you have specified the sample times
as port-based.
Languages C
10-46
ssGetInputPortOverWritable
Purpose 10ssGetInputPortOverWritable
Determine whether an input port can be overwritten.
Arguments S
SimStruct representing an S-function block or a Simulink model.
port
Index of the input port whose overwritability is being set.
Languages Ada, C
10-47
ssGetInputPortRealSignal
Purpose 10ssGetInputPortRealSignal
Get the address of a real, contiguous signal entering an input port.
Arguments S
SimStruct representing an S-function block.
inputPortIdx
Index of port whose sample time is required.
Description Returns the address of a real signal on the specified input port. A method
should use this macro only if the input signal is known to be real and
mdlIntializeSizes has specified that the elements of the input signal be
contiguous, using ssSetInputPortRequiredContiguous.
Languages C, C++
if ( ssGetInputPortRequiredContiguous(S,i) ) {
} else {
InputPtrsType u = ssGetInputPortSignalPtrs(S,i);
for (j = 0; j < nu; j++) {
UseInputInSomeFunction(*u[j]);
}
}
}
10-48
ssGetInputPortRealSignalPtrs
Purpose 10ssGetInputPortRealSignalPtrs
Get pointers to signals of type double connected to an input port.
Arguments S
SimStruct representing an S-function block.
port
Index of port whose signal is required.
Description Returns pointers to the elements of a signal of type double connected to port.
The input port index starts at 0 and ends at the number of input ports minus
1. This macro returns a pointer to an array of pointers to the real_T input
signal elements. The length of the array of pointers is equal to the width of the
input port.
Languages C
10-49
ssGetInputPortRequiredContiguous
Purpose 10ssGetInputPortRequiredContiguous
Determine whether the signal elements entering a port must be contiguous.
Arguments S
SimStruct representing an S-function block or a Simulink model.
port
Index of an input port
Description Returns true if the signal elements entering the specified port must occupy
contiguous areas of memory. If the elements are contiguous, a method can
access the elements of the signal simply by incrementing the signal pointer
returned by ssGetInputPortSignal.
Note The default setting for this flag is false. Hence, the default method for
accessing the input signals is ssGetInputSignalPtrs.
Languages C, C++
10-50
ssGetInputPortReusable
Purpose 10ssGetInputPortReusable
Determine whether memory allocated to input port is reusable.
Arguments S
SimStruct representing an S-function block or a Simulink model.
inputPortIdx
Index of the input port
Description Returns TRUE if input port memory buffer can be reused by other signals in
the model.
Languages C, C++
10-51
ssGetInputPortSampleTime
Purpose 10ssGetInputPortSampleTime
Get the sample time of an input port.
Arguments S
SimStruct representing an S-function block.
inputPortIdx
Index of port whose sample time is required.
Description Use in any routine (except mdlInitializeSizes) to determine the sample time
of an input port. You should use this macro only if you have specified the
sample times as port-based.
Languages C
10-52
ssGetInputPortSampleTimeIndex
Purpose 10ssGetInputPortSampleTimeIndex
Get the sample time index of an input port.
Arguments S
SimStruct representing an S-function block or a Simulink model.
inputPortIdx
Index of the input port whose sample time index is being set.
Description Returns the index of the sample time for the port.
Languages C, C++
10-53
ssGetInputPortSignal
Purpose 10ssGetInputPortSignal
Get the address of a contiguous signal entering an input port.
Arguments S
SimStruct representing an S-function block.
inputPortIdx
Index of port whose sample time is required.
Description Returns the address of the specified input port. A method should use this
macro only if mdlIntializeSizes has specified that the elements of the input
signal be contiguous, using ssSetInputPortRequiredContiguous.
Languages C, C++
if ( ssGetInputPortRequiredContiguous(S,i) ) {
} else {
InputPtrsType u = ssGetInputPortSignalPtrs(S,i);
for (j = 0; j < nu; j++) {
UseInputInSomeFunction(*u[j]);
}
}
}
If you know that the inputs are always real_T signals, the
ssGetInputPortSignal line in the above code snippet would be:
10-54
ssGetInputPortSignal
10-55
ssGetInputPortSignalAddress
Purpose 10ssGetInputPortSignalAddress
Get address of an input port’s signal.
Arguments S
SimStruct representing an S-function block.
port
Index of an input port
Languages Ada
Example The following code gets the signal connected to a block’s input port.
uWidth : Integer := ssGetInputPortWidth(S,0);
U : array(0 .. uWidth-1) of Real_T;
for U'Address use ssGetInputPortSignalAddress(S,0);
10-56
ssGetInputPortSignalPtrs
Purpose 10ssGetInputPortSignalPtrs
Get pointers to an input port’s signal elements.
Arguments S
SimStruct representing an S-function block.
port
Index of an input port
Description Returns a pointer to an array of signal element pointers for the specified input
port. For example, if the input port width is 5, this function returns a pointer
to a 5-element pointer array. Each element in the pointer array points to the
specific element of the input signal.
You must use ssGetInputPortRealSignalPtrs to get pointers to signals of
type double (real_T).
Languages C
Example Assume that the input port data types are int8_T.
int_T nInputPorts = ssGetNumInputPorts(S);
for (i = 0; i < nInputPorts; i++) {
InputPtrsType u = ssGetInputPortSignalPtrs(S,i);
InputInt8PtrsType uInt8 = (InputInt8PtrsType)u;
int_T nu = ssGetInputPortWidth(S,i);
for (j = 0; j < nu; j++) {
/* u[j] is an int8_T pointer that points to the j-th element
of the input signal.
*/
UseInputInSomeFunction(*u[j]);
}
10-57
ssGetInputPortWidth
Purpose 10ssGetInputPortWidth
Get the width of an input port.
Arguments S
SimStruct representing an S-function block.
port
Index of port whose width is required.
Description Get the input port number of elements. If the input port is a 1-D array with w
elements, this function returns w. If the input port is an M-by-N matrix, this
function returns m*n. If m or n is unknown, this function returns
DYNAMICALLY_SIZED. Use in any routine (except mdlInitializeSizes) to
determine the width of an input port.
Languages Ada, C
10-58
ssGetIWork
Purpose 10ssGetIWork
Get a block’s integer work vector.
Arguments S
SimStruct representing an S-function block.
Description Returns the integer work vector used by the block represented by S. The vector
consists of elements of type int_T and is of length ssGetNumRWork(S).
Typically, this vector is initialized in mdlStart or mdlInitializeConditions,
updated in mdlUpdate, and used in mdlOutputs. You can use this macro in the
simulation loop, mdlInitializeConditions, or mdlStart routines.
Languages C
10-59
ssGetModelName
Purpose 10ssGetModelName
Get the model name.
Arguments S
SimStruct representing an S-function block or a Simulink model.
Description If S is a SimStruct for an S-function block, this macro returns the name of the
S-function MEX-file associated with the block. If S is the root SimStruct, this
macro returns the name of the Simulink block diagram.
Languages C
10-60
ssGetModeVector
Purpose 10ssGetModeVector
Get the mode vector.
Arguments S
SimStruct representing an S-function block.
Languages C, C++
10-61
ssGetModeVectorValue
Purpose 10ssGetModeVectorValue
Get an element of a block’s mode vector.
Arguments S
SimStruct representing an S-function block.
elementx
Index of a mode vector element
Languages C, C++
10-62
ssGetNonsampledZCs
Purpose 10ssGetNonsampledZCs
Get the zero-crossing signal values.
Arguments S
SimStruct representing an S-function block.
Description Returns a pointer to the vector containing the current values of the signals that
the variable-step solver monitors for zero crossings. The variable step solver
tracks the signs of these signals to bracket points where they cross zero. The
solver then takes simulation time steps at the points where the zero crossings
occur. This vector has length ssGetNumNonsampledZCs(S).
Languages C
10-63
ssGetNumContStates
Purpose 10ssGetNumContStates
Get the number of continuous states that a block has.
Arguments S
SimStruct representing an S-function block or model.
Description Returns the number of continuous states in the block or model represented by
S.You can use this macro in any routine except mdlInitializeSizes.
Languages Ada, C
10-64
ssGetNumDataTypes
Purpose 10ssGetNumDataTypes
Get number of data types registered for this simulation, including built-in
types.
Arguments S
SimStruct representing an S-function block.
Description Returns the number of data types registered for this simulation. This includes
all custom data types registered by custom S-function blocks and all built-in
data types.
Languages C
10-65
ssGetNumDiscStates
Purpose 10ssGetNumDiscStates
Get the number of discrete states that a block has.
Arguments S
SimStruct representing an S-function block.
Languages C
10-66
ssGetNumDWork
Purpose 10ssGetNumDWork
Get the number of data type work vectors used by a block.
Arguments S
SimStruct representing an S-function block.
Languages C, C++
10-67
ssGetNumInputPorts
Purpose 10ssGetNumInputPorts
Get the number of input ports that a block has.
Arguments S
SimStruct representing an S-function block.
Description Use in any routine (except mdlInitializeSizes) to determine how many input
ports a block has.
Languages Ada, C
10-68
ssGetNumIWork
Purpose 10ssGetNumIWork
Get the size of a block’s integer work vector.
Arguments S
SimStruct representing an S-function block.
Description Returns the size of the integer (int_T) work vector used by the block
represented by S. You can use this macro in any routine except
mdlInitializeSizes
Languages C
10-69
ssGetNumModes
Purpose 10ssGetNumModes
Get the size of the mode vector.
Arguments S
SimStruct representing an S-function block.
Description Returns the size of the modes vector. You can use this macro in any routine
except mdlInitializeSizes
Languages C
10-70
ssGetNumNonsampledZCs
Purpose 10ssGetNumNonsampledZCs
Get the size of the zero-crossing vector.
Arguments S
SimStruct representing an S-function block.
Description Returns the size of the zero-crossing vector. You can use this macro in any
routine except mdlInitializeSizes
Languages C
10-71
ssGetNumOutputPorts
Purpose 10ssGetNumOutputPorts
Get the number of output ports that a block has.
Arguments S
SimStruct representing an S-function block.
Languages Ada, C
10-72
ssGetNumParameters
Purpose 10ssGetNumParameters
Get the number of parameters that this block has.
Arguments S
SimStruct representing an S-function block.
Languages Ada
10-73
ssGetNumRunTimeParams
Purpose 10ssGetNumRunTimeParams
Get the number of run-time parameters created by this S-function.
Arguments S
SimStruct representing an S-function block.
Description Use this function to get the number of run-time parameters created by this
S-function.
Languages C
10-74
ssGetNumPWork
Purpose 10ssGetNumPWork
Get the size of a block’s pointer work vector.
Arguments S
SimStruct representing an S-function block.
Description Returns the size of the pointer work vector used by the block represented by S.
You can use this macro in any routine except mdlInitializeSizes
Languages C
10-75
ssGetNumRWork
Purpose 10ssGetNumRWork
Get the size of a block’s floating-point work vector.
Arguments S
SimStruct representing an S-function block.
Description Returns the size of the floating-point (real_T) work vector used by the block
represented by S. You can use this macro in any routine except
mdlInitializeSizes
Languages C
10-76
ssGetNumSampleTimes
Purpose 10ssGetNumSampleTimes
Get the number of sample times that a block has.
Arguments S
SimStruct representing an S-function block.
Languages C
10-77
ssGetNumSFcnParams
Purpose 10ssGetNumSFcnParams
Get the number of parameters that an S-function block expects.
Arguments S
SimStruct representing an S-function block.
Description Returns the number of parameters that S expects the user to enter.
Languages C
10-78
ssGetOutputPortBeingMerged
Purpose 10ssGetOutputPortBeingMerged
Determine whether the output of this block is connected to a Merge block.
Arguments S
SimStruct representing an S-function block or a Simulink model.
port
Index of the output port
Description Returns TRUE if this output port signal is being merged with other signals
(this happens if the S-function block output port is directly or via connection
type blocks is connected to a Merge block). This macro retursn the correct
answer in and after the S-function’s mdlSetWorkWidths method.
Languages C, C++
10-79
ssGetOutputPortComplexSignal
Purpose 10ssGetOutputPortComplexSignal
Get the numeric type (complex or real) of an output port.
Arguments S
SimStruct representing an S-function block.
port
Index of an output port
Description Returns the numeric type of port: COMPLEX_NO (real signal), COMPLEX_YES
(complex signal) or COMPLEX_INHERITED (dynamically determined).
Languages C
10-80
ssGetOutputPortDataType
Purpose 10ssGetOutputPortDataType
Get the data type of an output port.
Arguments S
SimStruct representing an S-function block or a Simulink model.
port
Index of an output port
Description Returns the data type of the output port specified by port.
Languages Ada, C
10-81
ssGetOutputPortDimensions
Purpose 10ssGetOutputPortDimensions
Get the dimensions of the signal leaving an output port.
Arguments S
SimStruct representing an S-function block.
port
Index of an output port
Description Returns an array of integers that specifies the dimensions of the signal leaving
port, e.g., [4 2] for a 4-by-2 matrix array. The size of the dimensions array is
equal to the number of signal dimensions accepted by the port, e.g., 1 for a
vector signal or 2 for a matrix signal.
Languages C
10-82
ssGetOutputPortFrameData
Purpose 10ssGetOutputPortFrameData
Determine if a port accepts signal frames.
Arguments S
SimStruct representing an S-function block.
port
Index of an output port
• -1
Port outputs either frame or unframed data.
•0
Port outputs unframed data only.
•1
Port outputs frame data only.
Languages C
10-83
ssGetOutputPortNumDimensions
Purpose 10ssGetOutputPortNumDimensions
Get the offset time of an output port.
Arguments S
SimStruct representing an S-function block.
port
Index of output port.
Languages C
10-84
ssGetOutputPortOffsetTime
Purpose 10ssGetOutputPortOffsetTime
Get the offset time of an output port.
Arguments S
SimStruct representing an S-function block.
outputPortIdx
Index of output port.
Description Use in any routine (except mdlInitializeSizes) to determine the sample time
of an output port. This macro should only be used if you have specified
port-based sample times.
Languages C
10-85
ssGetOutputPortRealSignal
Purpose 10ssGetOutputPortRealSignal
Get a pointer to an output signal of type double (real_T).
Arguments S
SimStruct representing an S-function block.
port
Index of output port.
Languages C
10-86
ssGetOutputPortReusable
Purpose 10ssGetOutputPortReusable
Determine whether memory allocated to output port is reusable.
Arguments S
SimStruct representing an S-function block or a Simulink model.
port
Index of the output port
Description Returns TRUE if output port memory buffer can be reused by other signals in
the model.
Languages C, C++
10-87
ssGetOutputPortSampleTime
Purpose 10ssGetOutputPortSampleTime
Get the sample time of an output port.
Arguments S
SimStruct representing an S-function block.
outputPortIdx
Index of output port.
Description Use in any routine (except mdlInitializeSizes) to determine the sample time
of an output port. This macro should only be used if you have specified
port-based sample times.
Languages C
10-88
ssGetOutputPortSignal
Purpose 10ssGetOutputPortSignal
Get the vector of signal elements emitted by an output port.
Arguments S
SimStruct representing an S-function block.
port
Index of output port.
Note If the port outputs a signal of type double (real_T), you must use
ssGetOutputPortRealSignal to get the signal vector.
Example Assume that the output port data types are int16_T.
nOutputPorts = ssGetNumOutputPorts(S);
for (i = 0; i < nOutputPorts; i++) {
int16_T *y = (int16_T *)ssGetOutputPortSignal(S,i);
int_T ny = ssGetOutputPortWidth(S,i);
for (j = 0; j < ny; j++) {
SomeFunctionToFillInOutput(y[j]);
}
}
Languages C
10-89
ssGetOutputPortSignalAddress
Purpose 10ssGetOutputPortSignalAddress
Get address of an output port’s signal.
Arguments S
SimStruct representing an S-function block.
port
Index of an output port
Languages Ada
Example The following code gets the signal connected to a block’s input port.
yWidth : Integer := ssGetOutputPortWidth(S,0);
Y : array(0 .. yWidth-1) of Real_T;
for Y'Address use ssGetOutputPortSignalAddress(S,0);
10-90
ssGetOutputPortWidth
Purpose 10ssGetOutputPortWidth
Get the width of an output port.
Arguments S
SimStruct representing an S-function block.
outputPortIdx
Index of output port.
Languages Ada, C
10-91
ssGetPath
Purpose 10ssGetPath
Get the path of a block.
Arguments S
SimStruct representing an S-function block or a Simulink model.
Description If S is an S-function block, this macro returns the full Simulink path to the
block. If S is the root SimStruct of the model, this macro returns the model
name. In a C MEX S-function, in mdlInitializeSizes, if
strcmp(ssGetModelName(S),ssGetPath(S))==0
the S-function is being called from MATLAB and is not part of a simulation.
Languages Ada, C
10-92
ssGetParentSS
Purpose 10ssGetParentSS
Get the parent of a SimStruct.
Arguments S
SimStruct representing an S-function block or a Simulink model.
Note There is one SimStruct for each S-Function in your model and one for
the model itself. The structures are arranged as a tree with the model
SimStruct as the root. User-written S-functions should not use the
ssGetParentSS macro.
Languages C
10-93
ssGetPlacementGroup
Purpose 10ssGetPlacementGroup
Get the name of the placement group of a block.
Arguments S
SimStruct representing an S-function block or a Simulink model. The block
must be either a source block (i.e., a block without input ports) or a sink block
(i.e., a block without output ports).
Description Use this macro in mdlInitializeSizes to get the name of this block’s
placement group.
Languages C
10-94
ssGetPWork
Purpose 10ssGetPWork
Get a block’s pointer work vector.
Arguments S
SimStruct representing an S-function block.
Description Returns the pointer work vector used by the block represented by S. The vector
consists of elements of type void * and is of length ssGetNumRWork(S).
Typically, this vector is initialized in mdlStart or mdlInitializeConditions,
updated in mdlUpdate, and used in mdlOutputs. You can use this macro in the
simulation loop, mdlInitializeConditions, or mdlStart routines.
Languages C
10-95
ssGetRealDiscStates
Purpose 10ssGetRealDiscStates
Get a block’s discrete state vector.
Arguments S
SimStruct representing an S-function block.
Languages C
10-96
ssGetRootSS
Purpose 10ssGetRootSS
Get the root of a SimStruct hierarchy.
Arguments S
SimStruct representing an S-function block or a Simulink model.
Languages C
10-97
ssGetRunTimeParamInfo
Purpose 10ssGetRunTimeParamInfo
Gets the attributes of a run-time parameter.
Arguments S
SimStruct representing an S-function block.
param
Index of a run-time parameter
Description Returns the attributes of the run-time parameter specified by param. See the
documentation for ssSetRunTimeParamInfo for a description of the ssParamRec
structure returned by this function.
Languages C
10-98
ssGetRWork
Purpose 10ssGetRWork
Get a block’s floating-point work vector.
Arguments S
SimStruct representing an S-function block.
Description Returns the floating-point work vector used by the block represented by S. The
vector consists of elements of type real_T and is of length ssGetNumRWork(S).
Typically, this vector is initialized in mdlStart or mdlInitializeConditions,
updated in mdlUpdate, and used in mdlOutputs. You can use this macro in the
simulation loop, mdlInitializeConditions, or mdlStart routines.
Languages C
10-99
ssGetSampleTimeOffset
Purpose 10ssGetSampleTimeOffset
Get the period of the current sample time.
Arguments S
SimStruct representing an S-function block.
Languages Ada
10-100
ssGetSampleTimePeriod
Purpose 10ssGetSampleTimePeriod
Get the period of the current sample time.
Arguments S
SimStruct representing an S-function block.
Languages Ada
10-101
ssGetSFcnParam
Purpose 10ssGetSFcnParam
Get a parameter of an S-function block.
Arguments S
SimStruct representing an S-function block.
index
Index of the parameter to be returned.
Description Use in any routine to access a parameter entered in the S-function’s block
dialog box where index starts at 0 and is less than ssGetSFcnParamsCount(S).
Languages C
10-102
ssGetSFcnParamsCount
Purpose 10ssGetSFcnParamsCount
Get the number of block dialog parameters that an S-function block has.
Arguments S
SimStruct representing an S-function block.
Description Returns the number of parameters that a user can set for the block represented
by S.
Languages C
10-103
ssGetSimMode
Purpose 10ssGetSimMode
Get the simulation mode an S-function block.
Arguments S
SimStruct representing an S-function block or a Simulink model.
Languages C
10-104
ssGetSolverMode
Purpose 10ssGetSolverMode
Get the solver mode being used to solve the S-function.
Arguments S
SimStruct representing an S-function block or a Simulink model.
Languages C, C++
10-105
ssGetSolverName
Purpose 10ssGetSolverName
Get the name of the solver being used to solve the S-function.
Arguments S
SimStruct representing an S-function block or a Simulink model.
Description Returns a pointer (char *) to the name of the solver being used to solve the
S-function represented by S.
Languages C
10-106
ssGetStateAbsTol
Purpose 10ssGetStateAbsTol
Get the absolute tolerance used by the model’s variable step solver for a
specified state.
Arguments S
SimStruct representing an S-function block.
Description Use in mdlStart to get the absolute tolerance for a particular state.
Note Absolute tolerances are not allocated for fixed step solvers. Therefore,
you should not invoke this macro until you have verified that the simulation is
using a variable step solver, using ssIsVariableStepSolver.
Languages C, C++
10-107
ssGetT
Purpose 10ssGetT
Get the current simulation time.
Arguments S
SimStruct representing an S-function block.
Description Returns the current base simulation time (time_T) for the model. You can use
this macro in mdlOutputs and mdlUpdate to compute the output of your block.
Note Use this macro only if your block operates at the base rate of the model,
for example, if your block operates at a single, continuous rate. If your block
operates at multiple rates or operates at a single rate that is different from
the model’s base, use ssGetTaskTime to get the correct time for the current
task.
Languages Ada, C
10-108
ssGetTNext
Purpose 10ssGetTNext
Get the time of the next sample hit.
Arguments S
SimStruct representing an S-function block
Description Returns the next time that a sample hit occurs in a discrete S-function with a
variable sample time.
Languages C
10-109
ssGetTaskTime
Purpose 10ssGetTaskTime
Get the current time for the current task.
Arguments S
SimStruct representing an S-function block.
st_index
Index of the sample time corresponding to the task for which the current time
is to be returned.
Description Returns the current time (time_T) of the task corresponding to the sample rate
specified by st_index. You can use this macro in mdlOutputs and mdlUpdate to
compute the output of your block.
Languages C
10-110
ssGetTFinal
Purpose 10ssGetTFinal
Get the simulation stop time.
Arguments S
SimStruct representing an S-function block.
Languages Ada, C
10-111
ssGetTStart
Purpose 10ssGetTStart
Get the simulation start time.
Arguments S
SimStruct representing an S-function block.
Languages Ada, C
10-112
ssGetUserData
Purpose 10ssGetUserData
Access user data.
Arguments S
SimStruct representing an S-function block.
Languages C, C++
10-113
ssIsContinuousTask
Purpose 10ssIsContinuousTask
Determine if a task is continuous.
Arguments S
SimStruct representing an S-function block
tid
task ID
Description Use in mdlOutputs or mdlUpdate when your S-function has multiple sample
times to determine if your S-function is executing in the continuous task. This
should not be used in single rate S-functions, or if you did not register a
continuous sample time.
Languages C
10-114
ssIsFirstInitCond
Purpose 10ssIsFirstInitCond
Determine whether this is the first call to mdlInitializeConditions.
Arguments S
SimStruct representing an S-function block.
Description Returns true if the current simulation time is equal to the simulation start
time.
Languages C
10-115
ssIsMajorTimeStep
Purpose 10ssIsMajorTimeStep
Determine if the simulation is in a major step.
Arguments S
SimStruct representing an S-function block
Languages Ada, C
10-116
ssIsMinorTimeStep
Purpose 10ssIsMinorTimeStep
Determine if the simulation is in a minor step.
Arguments S
SimStruct representing an S-function block
Languages C
10-117
ssIsSampleHit
Purpose 10ssIsSampleHit
Determine if sample is hit.
Arguments S
SimStruct representing an S-function block
st_index
Index of the sample time
tid
task ID
Description Use in mdlOutputs or mdlUpdate when your S-function has multiple sample
times to determine what task your S-function is executing in. This should not
be used in single rate S-functions or for an st_index corresponding to a
continuous task.
Languages C
10-118
ssIsSpecialSampleHit
Purpose 10ssIsSpecialSampleHit
Determine if sample is hit.
Arguments S
SimStruct representing an S-function block
sti1
Index of the sample time
sti2
Index of the sample time
tid
task ID
Description Returns true if a sample hit has occurred at sti1 and a sample hit has also
occurred at sti2 in the same time step. You can used this macro in mdlUpdate
and mdlOutputs to ensure the validity of data shared by multiple tasks running
at different rates. For more information, see “Synchronizing Multirate
S-Function Blocks” on page 7-22.
Languages C
10-119
ssIsVariableStepSolver
Purpose 10ssIsVariableStepSolver
Get the name of the solver being used to solve the S-function.
Arguments S
SimStruct representing an S-function block or a Simulink model.
Description Returns 1 if the solver being used to solve S is a variable step solver. This is
useful when creating S-functions that have zero crossings and an inherited
sample time.
Languages C
10-120
ssPrintf
Purpose 10ssPrintf
Print a variable-content message.
Arguments msg
Message. Must be a string with optional variable replacement parameters.
...
Optional replacement arguments.
Description Prints variable-content msg. This macro expands to mexPrintf when the
S-function is compiled via mex for use with Simulink. When the S-function is
compiled for use with the Real-Time Workshop, this macro expands to printf,
if the target has stdio facilities; otherwise, it becomes a call to an empty
function (rtPrintfNoOp). In the case of Real-Time Workshop, you can avoid a
call altogether, using the SS_STDIO_AVAILABLE macro, e.g.,
#if defined(SS_STDIO_AVAILABLE)
ssPrintf("my message ...");
#endif
Languages C
10-121
ssRegAllTunableParamsAsRunTimeParams
Purpose 10ssRegAllTunableParamsAsRunTimeParams
Register all tunable parameters as run-time parameters.
Arguments S
SimStruct representing an S-function block.
names
Array of names for the run-time parameters
Note Simulink assumes that the names array is always available. Therefore,
you must allocate the names array in such a way that it persists throughout
the simulation.
Languages C
10-122
ssRegisterDataType
Purpose 10ssRegisterDataType
Register a custom data type.
Arguments S
SimStruct representing an S-function block.
name
Name of custom data type
Description Register a custom data type. Each data type must be a valid MATLAB
identifier. That is, the first char is an alpha and all subsequent characters are
alphanumeric or “_”. The name length must be less than 32. Data types must
be registered in mdlInitializeSizes.
If the registration is successful, the function returns the DataTypeId associated
with the registered data type, otherwise, it reports an error and returns
INVALID_DTYPE_ID.
After registering the data type, you must specify its size, using
ssSetDataTypeSize.
Note You can call this function to get the data type id associated with a
registered data type.
Example The following example registers a custom data type named Color.
DtypeId id = ssRegisterDataType(S, “Color”);
if(id == INVALID_DTYPE_ID) return;
Languages C
10-123
ssSetBlockReduction
Purpose 10ssSetBlockReduction
Request that Simulink attempt to reduce a block.
Arguments S
SimStruct representing an S-function block
flag
If TRUE, Simulink should attempt to reduce this block.
Description Use this macro to ask Simulink to reduce this block. A block is reducible if it
can be eliminated from the model without affecting the model’s behavior.
Simulink optimizes performance by skipping execution of reducible blocks
during model simulation. In particular, Simulink does not invoke the
mdlStart, mdlUpdate, and mdlOutput methods of reducible blocks. Further,
Simulink executes the mdlTerminate method of a reduced block only if the
block has set the SS_OPTION_CALL_TERMINATE_AT_EXIT option before the
simulation loop has begun, using ssSetOption.
A block must meet certain criteria to be considered reducible. For example, a
block must have at least one input, must have the same number of outputs as
inputs or no outputs, and none of the block’s inputs can be a bus signal. If a
block fails to meet any of these criteria, Simulink includes the block in the
simulation regardless of whether the block has requested reduction.
Your S-function must invoke this macro before Simulink would otherwise
invoke the S-function’s mdlStart method (see the callback flow diagram in
“How Simulink Interacts with C S-Functions” on page 3-32). This means your
S-function must invoke this macro no later than its mdlInitializeWorkWidths
method to be considered a candidate for block reduction.
Languages C
10-124
ssSetCallSystemOutput
Purpose 10ssSetCallSystemOutput
Specify that an output port is issuing a function call.
Arguments S
SimStruct representing an S-function block or a Simulink model.
port_index
Index of port that is issuing the function call
Languages C
10-125
ssSetDataTypeSize
Purpose 10ssSetDataTypeSize
Set the size of a custom data type.
Arguments S
SimStruct representing an S-function block.
id
ID of data type
size
Size of the custom data type in bytes
Description Sets the size of the data type specified by id to size. If the call is successful,
the macro returns 1 (true), otherwise, it returns 0 (false).Use this macro in
mdlInitializeSizes to set the size of a data type you have registered.
Example The following example registers and sets the size of the custom data type
named Color to four bytes.
int_T status;
DtypeId id;
Languages C
10-126
ssSetDataTypeZero
Purpose 10ssSetDataTypeZero
Set zero representation of a data type.
Arguments S
SimStruct representing an S-function block.
id
ID of data type
zero
Zero representation of the data type specified by id
Description Sets the zero representation of the data type specified by id to zero and
returns 1 (true), if id valid, and the size of the data type has been set, and the
zero representation has not already been set. Otherwise, this macro returns 0
(false) and reports an error. Because this macro reports any error that occurs,
you do not need to use ssSetErrorStatus to report the error.
Note This macro makes a copy of the zero representation of the data type for
Simulink’s use. Thus, your S-function does not have to maintain the original
in memory.
Languages C
Example The following example registers and sets the size and zero representation of a
custom data type named myDataType.
typedef struct{
int8_T a;
uint16_T b;
}myStruct;
int_T status;
DtypeId id;
myStruct tmp;
id = ssRegisterDataType(S, “myDataType”);
10-127
ssSetDataTypeZero
tmp.a = 0;
tmp.b = 1;
status = ssSetDataTypeZero(S, id, &tmp);
if(status == 0) return;
10-128
ssSetDWorkComplexSignal
Purpose 10ssSetDWorkComplexSignal
Specify whether the elements of a data type work vector are real or complex.
Arguments S
SimStruct representing an S-function block.
vector
Index of a data type work vector, where the index is one of 0, 1, 2, ...
ssGetNumDWork(S)
numType
Numeric type, either COMPLEX_YES or COMPLEX_NO.
Languages C, C++
10-129
ssSetDWorkDataType
Purpose 10ssSetDWorkDataType
Specify the data type of a data type work vector.
Arguments S
SimStruct representing an S-function block.
vector
Index of a data type work vector, where the index is one of 0, 1, 2, ...
ssGetNumDWork(S)
dtID
Id of a data type
Languages C, C++
10-130
ssSetDWorkName
Purpose 10ssSetDWorkName
Specify the name of a data type work vector.
Arguments S
SimStruct representing an S-function block.
name
Index of the work vector, where the index is one of 0, 1, 2, ...
ssGetNumDWork(S)
name
Name of work vector.
Languages C, C++
10-131
ssSetDWorkUsedAsDState
Purpose 10ssSetDWorkUsedAsDState
Specify that a data type work vector is used as a discrete state vector.
Arguments S
SimStruct representing an S-function block.
vector
Index of a data type work vector, where the index is one of 0, 1, 2, ...
ssGetNumDWork(S)
Usage
How this vector is used
Languages C, C++
10-132
ssSetDWorkWidth
Purpose 10ssSetDWorkWidth
Specify the width of a data type work vector.
Arguments S
SimStruct representing an S-function block.
vector
Index of the work vector, where the index is one of 0, 1, 2, ...
ssGetNumDWork(S)
width
Number of elements in the work vector.
Languages C, C++
10-133
ssSetErrorStatus
Purpose 10ssSetErrorStatus
Report an error.
Arguments S
SimStruct representing an S-function block or a Simulink model.
msg
Error message
Description Use this function to report errors that occur in your S-function, e.g.,
ssSetErrorStatus(S, "error message");
return;
Languages Ada, C
10-134
ssSetExternalModeFcn
Purpose 10ssSetExternalModeFcn
Specify the external mode function for an S-function.
Arguments S
SimStruct representing an S-function block or a Simulink model.
fcn
external mode function
Languages C
10-135
ssSetInputPortComplexSignal
Purpose 10ssSetInputPortComplexSignal
Set the numeric type (real or complex) of an input port.
Arguments S
SimStruct representing an S-function block or a Simulink model.
port
Index of an input port
csignal
Numeric type of the signals accepted by port. Valid values are COMPLEX_NO
(real signal), COMPLEX_YES (complex signal), COMPLEX_INHERITED (numeric type
inherited from driving block).
Description Use this function in mdlInitializeSizes to initialize input port signal type. If
the numeric type of the input port is inherited from the block to which it is
connected, set the numeric type to COMPLEX_INHERITED. The default numeric
type of an input port is real.
Languages C
Example Assume that an S-function has three input ports. The first input port accepts
real (non-complex) signals. The second input port accepts complex signal. The
third port accepts signals of either type. The following example specifies the
correct numeric type for each port.
ssSetInputPortComplexSignal(S, 0, COMPLEX_NO)
ssSetInputPortComplexSignal(S, 1, COMPLEX_YES)
ssSetInputPortComplexSignal(S, 2, COMPLEX_INHERITED)
10-136
ssSetInputPortDataType
Purpose 10ssSetInputPortDataType
Set the data type of an input port.
Arguments S
SimStruct representing an S-function block or a Simulink model.
port
Index of an input port
id
Id of data type accepted by port
Description Use this function in mdlInitializeSizes to set the data type of the input port
specified by port. If the input port’s data type is inherited from the block
connected to the port, set the data type to DYNAMICALLY_TYPED.
Languages Ada, C
Example Suppose that you want to create an S-function with two input ports, the first of
which inherits its data type the driving block and the second of which accepts
inputs of type int8_T. The following code sets up the data types.
ssSetInputPortDataType(S, 0, DYNAMICALLY_TYPED)
ssSetInputPortDataType(S, 1, SS_INT8)
10-137
ssSetInputPortDimensionInfo
Purpose 10ssSetInputPortDimensionInfo
Specify information about the dimensionality of an input port.
Arguments S
SimStruct representing an S-function block.
port
Index of an input port
dimsInfo
Structure of type DimsInfo_T that specifies the dimensionality of the signals
accepted by port.
The structure is defined as
typedef struct DimsInfo_tag{
int width;/* number of elements */
int numDims/* Number of dimensions */
int *dims;/* Dimensions. */
[snip]
}DimsInfo_T;
where:
• numDims specifies the number of dimensions of the signal, e.g., 1 for a 1-D
(vector) signal or 2 for a 2-D (matrix) signal, or DYNAMICALLY_SIZED if the
number of dimensions is determined dynamically
• dims is an integer array that specifies the size of each dimension, e.g., [2 3]
for a 2-by-3 matrix signal, or DYNAMICALLY_SIZED for each dimension that
is determined dynamically, e.g., [2 DYNAMICALL_SIZED]
• width equals the total number of elements in the signal, e.g., 12 for a 3-by-4
matrix signal or 8 for an 8-element vector signal, or DYNAMICALLY_SIZED if
the total number of elements is determined dynamically
10-138
ssSetInputPortDimensionInfo
Description Specifies the dimension information for port. Use this function in
mdlInitializeSizes to initialize the input port dimension information. If you
want the port to inherit its dimensions from the port to which it is connected,
specify DYNAMIC_DIMENSION as the dimsInfo for port.
Languages C
Example The following example specifies that input port 0 accepts 2-by-2 matrix signals.
{
DECL_AND_INIT_DIMSINFO(di);
int dims[2];
di.numDims = 2;
dims[0] = 2;
dims[1] = 2;
di.dims = &dims;
di.width = 4;
ssSetInputPortDimensionInfo(S, 0, &di);
}
10-139
ssSetInputPortFrameData
Purpose 10ssSetInputPortFrameData
Specify whether a port accepts signal frames.
Arguments S
SimStruct representing an S-function block.
port
Index of an input port
acceptsFrames
Type of signal accepted by port. Acceptable values are -1 (either frame or
unframed input), 0 (unframed input only), 1 (framed input only).
Languages C
10-140
ssSetInputPortDirectFeedThrough
Purpose 10ssSetInputPortDirectFeedThrough
Specify the direct feedthrough status of a block’s ports.
Arguments S
SimStruct representing an S-function block or a Simulink model.
port
Index of the input port whose direct feedthrough property is being set.
dirFeed
Direct feedthrough status of block specified by inputPortIdx.
Languages Ada, C
10-141
ssSetInputPortMatrixDimensions
Purpose 10ssSetInputPortMatrixDimensions
Specify dimension information for an input port that accepts matrix signals.
Arguments S
SimStruct representing an S-function block.
port
Index of an input port
m
Row dimension of matrix signals accepted by port or DYNAMICALLY_SIZED
n
Column dimension of matrix signals accepted by port or DYNAMICALLY_SIZED
Description Specifies that port accepts an m-by-n matrix signal. If either dimension is
DYNAMICALLY_SIZED, the other must be DYNAMICALLY_SIZED or 1.
Languages C
Example The following example specifies that input port 0 accepts 2-by-2 matrix signals.
ssSetInputPortMatrixDimensions(S, 0, 2, 2);
10-142
ssSetInputPortOffsetTime
Purpose 10ssSetInputPortOffsetTime
Specify the offset time of an input port.
Arguments S
SimStruct representing an S-function block or a Simulink model.
inputPortIdx
Index of the input port whose offset time is being set.
offset
Offset time
Languages C
10-143
ssSetInputPortOverWritable
Purpose 10ssSetInputPortOverWritable
Specify whether an input port can be overwritten.
Arguments S
SimStruct representing an S-function block or a Simulink model.
port
Index of the input port whose overwritability is being set.
isOverwritable
Value specifying whether port is overwritable.
Languages Ada, C
10-144
ssSetInputPortReusable
Purpose 10ssSetInputPortReusable
Specify whether where memory allocated to port is reusable.
Arguments S
SimStruct representing an S-function block or a Simulink model.
inputPortIdx
Index of the input port whose reusability is being set.
isReusable
Value specifying whether port is reusable.
• Off (isReusable=0) — specifies that the input port is not reusable. This is the
default.
• On (isReusable=1) — specifies that the input port is reusable.
In Simulink, reusable signals share the same memory space. When this macro
is turned on, the input port signal to the S-function may be reused by other
signals in the model. This reuse results in less memory use during Simulink
simulation and more efficiency in the Real-Time Workshop generated code.
You must use caution when using this macro; you can safely turn it on only if
the S-function reads its input port signal in its mdlOutputs routine and does
not access this input port signal until the next call to mdlOutputs.
When an S-functions’s input port signal is reused, other signals in the model
overwrite it prior to the execution of mdlUpdate, mdlDerivatives, or other
run-time S-function routines. For example, if the S-function reads the input
port signal in its mdlUpdate routine, or reads the input port signal in the
mdlOutputs routine and expects this value to be persistent until the execution
of its mdlUpdate routine, turning this attribute on is incorrect and will lead to
erroneous results.
The default setting, off, is safe. It prevents any reuse of the S-function input
port signals, which means that the inport port signals have the same value in
10-145
ssSetInputPortReusable
Languages C
10-146
ssSetInputPortRequiredContiguous
Purpose 10ssSetInputPortRequiredContiguous
Specify that the signal elements entering a port must be contiguous.
Arguments S
SimStruct representing an S-function block or a Simulink model.
port
Index of an input port
flag
TRUE if signal elements must be contiguous.
Description Specifies that the signal elements entering the specified port must occupy
contiguous areas of memory. This allows a method to access the elements of the
signal simply by incrementing the signal pointer returned by
ssGetInputPortSignal. The S-function can set the value of this attribute as
early as in the mdlInitializeSizes method and at the latest in the
mdlSetWorkWidths method.
Note The default setting for this flag is false. Hence, the default method for
accessing the input signals is ssGetInputSignalPtrs.
Languages C, C++
10-147
ssSetInputPortSampleTime
Purpose 10ssSetInputPortSampleTime
Specify the sample time of an input port.
Arguments S
SimStruct representing an S-function block or a Simulink model.
inputPortIdx
Index of the input port whose sample time is being set.
period
Sample period.
Languages C
10-148
ssSetInputPortSampleTimeIndex
Purpose 10ssSetInputPortSampleTimeIndex
Specify the sample time index of an input port.
Arguments S
SimStruct representing an S-function block or a Simulink model.
inputPortIdx
Index of the input port whose sample time index is being set.
sampleTimeIdx
Sample time index.
Note This should only be used when the PORT_BASED_SAMPLE_TIMES has been
specified for ssSetNumSampleTimes in mdlInitializeSizes.
Languages C, C++
10-149
ssSetInputPortVectorDimension
Purpose 10ssSetInputPortVectorDimension
Specify dimension information for an input port that accepts vector signals.
Arguments S
SimStruct representing an S-function block.
port
Index of an input port
w
Width of vector or DYNAMICALLY_SIZED
Languages C
Example The following example specifies that input port 0 accepts an 8-element matrix
signal.
ssSetInputPortVectorDimension(S, 0, 8);
10-150
ssSetInputPortWidth
Purpose 10ssSetInputPortWidth
Specify the number of input ports that a block has.
Arguments S
SimStruct representing an S-function block or a Simulink model.
port
Index of the input port whose width is being set.
width
Width of input port.
Languages Ada, C
10-151
ssSetModeVectorValue
Purpose 10ssSetModeVectorValue
Set an element of a block’s mode vector.
Arguments S
SimStruct representing an S-function block.
element
Index of a mode vector element
value
Mode vector value
Description Sets the specified mode vector element to the specified value.
Languages C, C++
10-152
ssSetNumContStates
Purpose 10ssSetNumContStates
Specify the number of continuous states that a block has.
Arguments S
SimStruct representing an S-function block.
n
Number of continuous states to be set for the block represented by S.
Languages Ada, C
10-153
ssSetNumDiscStates
Purpose 10ssSetNumDiscStates
Specify the number of discrete states that a block has.
Arguments S
SimStruct representing an S-function block.
nDiscStates
Number of discrete states to be set for the block represented by S.
Languages C
10-154
ssSetNumDWork
Purpose 10ssSetNumDWork
Specify the number of data type work vectors used by a block.
Arguments S
SimStruct representing an S-function block.
DWork
Number of data type work vectors.
Description Use in mdlInitializeSizes to specify the number of data type work vectors as
0, a positive integer, or DYNAMICALLY_SIZED. If you specify DYNAMICALLY_SIZED,
you can specify the true (positive integer) number of vectors in
mdlSetWorkWidths.
You can specify the size and data type of each work vector, using the macros
ssSetDWorkWidth and ssSetDWorkDataType, respectively. You can also specify
that the work vector holds complex values, using ssSetDWorkComplexSignal.
Languages C, C++
10-155
ssSetNumInputPorts
Purpose 10ssSetNumInputPorts
Specify the number of input ports that a block has.
Arguments S
SimStruct representing an S-function block.
nInputPorts
Number of input ports on the block represented by S. Must be a nonnegative
integer.
Languages Ada, C
10-156
ssSetNumIWork
Purpose 10ssSetNumIWork
Specify the size of a block’s integer work vector.
Arguments S
SimStruct representing an S-function block.
nIWork
Number of elements in the integer work vector.
Languages C
10-157
ssSetNumModes
Purpose 10ssSetNumModes
Specifies the size of the block’s mode vector.
Arguments S
SimStruct representing an S-function block.
nModes
Size of the mode vector for the block represented by S. Valid values are 0, a
positive integer, or DYNAMICALLY_SIZED.
Description Sets the size of the block’s mode vector to nModes. If nModes is
DYNAMICALLY_SIZED, you can specify the true (positive integer) width in
mdlSetWorkWidths, otherwise the width used is the width of the signal passing
through the block. Use this macro in mdlInitializeSizes to specify the
number of int_T elements in the mode vector. Simulink allocates the mode
vector and initializes its elements to 0. If the default value of 0 is not
appropriate, you can set the elements of the array to other initial values in
mdlInitializeConditions. Use ssGetModeVector to access the mode vector.
The mode vector, combined with zero-crossing detection, allows you to create
blocks that have distinct operating modes, depending on the current values of
input or output signals. For example, consider a block that outputs the absolute
value of its input. Such a block operates in two distinct modes, depending on
whether its input is positive or negative. If the input is positive, the block
outputs the input unchanged. If the input is negative, the block outputs the
negative of the input. You can use zero-crossing detection to detect when the
input changes sign and update the single-element mode vector accordingly (for
example, by setting its element to 0 for negative input and 1 for positive input).
You can then use the mode vector in mdlOutputs to determine the mode in
which the block is currently operating.
Languages C
10-158
ssSetNumNonsampledZCs
Purpose 10ssSetNumNonsampledZCs
Specify the number of states for which a block detects zero crossings that occur
between sample points.
Arguments S
SimStruct representing an S-function block.
nNonsampledZCs
Number of nonsampled zero crossings that a block detects.
Description Use in mdlInitializeSizes to specify the number of states for which the block
detects nonsampled zero crossings (real_T) as 0, a positive integer, or
DYNAMICALLY_SIZED. If you specify DYNAMICALLY_SIZED, you can specify the
true (positive integer) width in mdlSetWorkWidths, otherwise the width to be
used will be the width of the signal passing through the block.
Languages C
10-159
ssSetNumOutputPorts
Purpose 10ssSetNumOutputPorts
Specify the number of output ports that a block has.
Arguments S
SimStruct representing an S-function block.
nOutputPorts
Number of output ports on the block represented by S. Must be a nonnegative
integer.
Languages Ada, C
10-160
ssSetNumPWork
Purpose 10ssSetNumPWork
Specify the size of a block’s pointer work vector.
Arguments S
SimStruct representing an S-function block.
nPWork
Number of elements to be allocated to the pointer work vector of the block
represented by S.
Languages C
10-161
ssSetNumRunTimeParams
Purpose 10ssSetNumRunTimeParams
Specify the number of run-time parameters created by this S-function.
Arguments S
SimStruct representing an S-function block.
num
Number of run-time parameters
Languages C
10-162
ssSetNumRWork
Purpose 10ssSetNumRWork
Specify the size of a block’s floating-point work vector.
Arguments S
SimStruct representing an S-function block.
nRWork
Number of elements in the floating-point work vector.
Languages C
10-163
ssSetNumSampleTimes
Purpose 10ssSetNumSampleTimes
Specify the number of sample times that an S-function block has.
Arguments S
SimStruct representing an S-function block.
nSampleTimes
Number of sample times that S has.
Description Use in mdlInitializeSizes to set the number of sample times S has. This
must be a positive integer greater than 0.
Languages C
10-164
ssSetNumSFcnParams
Purpose 10ssSetNumSFcnParams
Specify the number of parameters that an S-function block has.
Arguments S
SimStruct representing an S-function block.
nSFcnParams
Number of parameters that S has.
Languages C
10-165
ssSetOffsetTime
Purpose 10ssSetOffsetTime
Set the offset time of a block.
Arguments S
SimStruct representing an S-function block.
st_index
Index of sample time whose offset is to be set.
offset
Offset of the sample time specified by st_index
Description Use this macro in mdlInitializeSizes to specify the offset of the sample time
where st_index starts at 0.
Languages C
10-166
ssSetOptions
Purpose 10ssSetOptions
Specify S-function options.
Arguments S
SimStruct representing an S-function block.
options
Options
S-Function Options
An S-function can specify the following options, using ssSetOptions:
• SS_OPTION_EXCEPTION_FREE_CODE
If your S-function does not use mexErrMsgTxt, mxCalloc, or any other
routines that can throw an exception when called, you can set this option for
improved performance.
• SS_OPTION_RUNTIME_EXCEPTION_FREE_CODE
Similar to SS_OPTION_EXCEPTION_FREE_CODE except it only applies to the
“run-time” routines: mdlGetTimeOfNextVarHit, mdlOutputs, mdlUpdate, and
mdlDerivatives.
• SS_OPTION_DISCRETE_VALUED_OUTPUT
Specify this if your S-function has discrete valued outputs. This is checked
when your S-function is placed within an algebraic loop. If your S-function
has discrete valued outputs, then its outputs will not be assigned algebraic
variables.
• SS_OPTION_PLACE_ASAP
Used to specify that your S-function should be placed as soon as possible.
This is typically used by devices connecting to hardware.
10-167
ssSetOptions
• SS_OPTION_ALLOW_INPUT_SCALAR_EXPANSION
Used to specify that the input to your S-function input ports can be either 1
or the size specified by the port, which is usually referred to as the block
width.
• SS_OPTION_DISALLOW_CONSTANT_SAMPLE_TIME
Use to disable an S-function block from inheriting a constant sample time.
• SS_OPTION_ASYNCHRONOUS
This option applies only to S-functions that have 0 or 1 input ports and 1
output port. The output port must be configured to perform function calls on
every element. If any of these requirements are not met, the
SS_OPTION_ASYNCHRONOUS is ignored. Use this option when driving
function-call subsystems that will be attached to interrupt service routines.
• SS_OPTION_ASYNC_RATE_TRANSITION
Use this when your S-function converts a signal from one rate to another
rate.
• SS_OPTION_RATE_TRANSITION
Use this option when your S-function is behaving as a unit delay or a ZOH.
This macro support these two operations only. It identifies a unit delay by the
presence of mdlUpdate; if mdlUpdate is absent, the operation is taken to be
ZOH.
• SS_OPTION_PORT_SAMPLE_TIMES_ASSIGNED
Use this when you have registered multiple sample times
(ssSetNumSampleTimes > 1) to specify the rate at when each input and
output port is running at. The simulation engine needs this information
when checking for illegal rate transitions.
• SS_OPTION_SFUNCTION_INLINED_FOR_RTW
Set this if you have a .tlc file for your S-function and do not have a mdlRTW
method. Setting option has no effect if you have a mdlRTW method.
• SS_OPTION_ALLOW_PARTIAL_DIMENSIONS_CALL
Indicates that the S-function can handle dynamically dimensioned signals.
See mdlSetInputPortDimensions, mdlSetOutputPortDimensions, or
mdlSetDefaultPortDimensions for more information.
10-168
ssSetOptions
• SS_OPTION_FORCE_NONINLINED_FCNCALL
Use this flag if the block requires that all function-call subsystems that it
calls should be generated as procedures instead of possibly being generated
as inlined code.
• SS_OPTION_USE_TLC_WITH_ACCELERATOR
Use this to force the Accelerator to use the TLC inlining code for a S-function
which will speed up execution of the S-function. By default, the Accelerator
will use the mex version of the S-function even though a TLC file for the
S-function exists. This option should not be set for device driver blocks (A/D)
or when there is an incompatability between running the mex Start/
InitializeConditions functions together with the TLC Outputs/Update/
Derivatives.
• SS_OPTION_SIM_VIEWING_DEVICE
This S-function is a SimViewingDevice. As long as it meets the other
requirement for this type of block (no states, no outputs, etc), it will be
considered to be an external mode block (show up in the external mode GUI
and no code is generated for it). During an external mode simulation, this
block is run on the host only.
• SS_OPTION_CALL_TERMINATE_ON_EXIT
This option allows S-function authors to better manage the data cached in
run-time parameters and UserData. Setting this option guarantees that the
mdlTerminate function is called if mdlInitializeSizes is called. This means
that mdlTerminate is called:
10-169
ssSetOptions
• SS_OPTION_REQ_INPUT_SAMPLE_TIME_MATCH
Use this to option to specify that the input signal sample time(s) match the
sample time assigned to the block input port. For example,
S-function
src(0.1) Port-based Ts = 1
generates an error if this option is set. If the block (or input port) sample
time is inherited, then there will be no error generated.
Languages C, C++
10-170
ssSetOutputPortComplexSignal
Purpose 10ssSetOutputPortComplexSignal
Set the numeric type (real or complex) of an output port.
Arguments S
SimStruct representing an S-function block or a Simulink model.
port
Index of an output port
csignal
Numeric type of the signals emitted by port. Valid values are COMPLEX_NO (real
signal), COMPLEX_YES (complex signal), COMPLEX_INHERITED (dynamically
determined).
Description Use this function in mdlInitializeSizes to initialize input port signal type. If
the numeric type of the input port is determined dynamically, e.g., by a
parameter setting, set the numeric type to COMPLEX_INHERITED. The default
numeric type of an output port is real.
Languages C
Example Assume that an S-function has three output ports. The first output port emits
real (non-complex) signals. The second input port emits a complex signal. The
third port emits signals of a type determined by a parameter setting. The
following example specifies the correct numeric type for each port.
ssSetOutputPortComplexSignal(S, 0, COMPLEX_NO)
ssSetOutputPortComplexSignal(S, 1, COMPLEX_YES)
ssSetOutputPortComplexSignal(S, 2, COMPLEX_INHERITED)
10-171
ssSetOutputPortDataType
Purpose 10ssSetOutputPortDataType
Set the data type of an output port.
Arguments S
SimStruct representing an S-function block or a Simulink model.
port
Index of an input port
id
Id of data type accepted by port
Description Use this function in mdlInitializeSizes to set the data type of the output port
specified by port. If the input port’s data type is determined dynamically, for
example, from the data type of a block parameter, set the data type to
DYNAMICALLY_TYPED.
Languages Ada, C
Example Suppose that you want to create an S-function with two input ports, the first of
which gets its data type from a block parameter and the second of which
outputs signals of type int16_T. The following code sets up the data types.
ssSetInputPortDataType(S, 0, DYNAMICALLY_TYPED)
ssSetInputPortDataType(S, 1, SS_INT16)
10-172
ssSetOutputPortDimensionInfo
Purpose 10ssSetOutputPortDimensionInfo
Specify information about the dimensionality of an output port.
Arguments S
SimStruct representing an S-function block.
port
Index of an output port
dimsInfo
Structure of type DimsInfo_T that specifies the dimensionality of the signals
emitted by port
See ssSetInputPortDimensionInfo for a description of this structure.
Description Specifies the dimension information for port. Use this function in
mdlInitializeSizes to initialize the output port dimension info. If you want
the port to inherit its dimensionality from the block to which it is connected,
specify DYNAMIC_DIMENSION as the dimsInfo for port.
Languages C
Example The following example specifies that input port 0 accepts 2-by-2 matrix signals.
DECL_AND_INIT_DIMSINFO(di);
di.numDims = 2;
int dims[2];
dims[0] = 2;
dims[1] = 2;
di.dims = &dims;
di.width = 4;
ssSetOutputPortDimensionInfo(S, 0, &di);
10-173
ssSetOutputPortFrameData
Purpose 10ssSetOutputPortFrameData
Specify whether a port outputs framed data.
Arguments S
SimStruct representing an S-function block.
port
Index of an output port
outputsFrames
Type of signal output by port. Acceptable values are -1 (either frame or
unframed input), 0 (unframed input only), 1 (framed input only).
Languages C
10-174
ssSetOutputPortMatrixDimensions
Purpose 10ssSetOutputPortMatrixDimensions
Specify dimension information for an output port that emits matrix signals.
Arguments S
SimStruct representing an S-function block.
port
Index of an input port
m
Row dimension of matrix signals emitted by port or DYNAMICALLY_SIZED
n
Column dimension of matrix signals emitted by port or DYNAMICALLY_SIZED
Description Specifies that port emits an m-by-n matrix signal. If either dimension is
DYNAMICALLY_SIZED, the other must be DYNAMICALLY_SIZED or 1.
Languages C
Example The following example specifies that input port 0 emits 2-by-2 matrix signals.
ssSetOutputPortDimensionInfo(S, 0, 2, 2);
10-175
ssSetOutputPortOffsetTime
Purpose 10ssSetOutputPortOffsetTime
Specify the offset time of an output port.
Arguments S
SimStruct representing an S-function block.
outputPortIdx
Index of the output port whose sample time is being set.
period
Sample time of output port.
Languages C
10-176
ssSetOutputPortReusable
Purpose 10ssSetOutputPortReusable
Specify that an output port is reusable.
Arguments S
SimStruct representing an S-function block.
outputPortIdx
Index of the output port whose reusability is being set.
isReusable
Value specifying reusability of port
• Off (isReusable=0) — specifies that the output port is not reusable. This is
the default.
• On (isReusable=1) — specifies that the output port is reusable.
In Simulink, reusable signals share the same memory space. When this macro
is turned on, the output port signal to the S-function may be reused by other
signals in the model. This reuse results in less memory use during Simulink
simulation and more efficiency in the Real-Time Workshop generated code.
When you mark an output port as reusable, your S-function must update the
output once in mdlOutputs. It cannot expect the previous output value to be
persistent.
By default, the output port signals are not reusable. This forces Simulink’s
simulation engine (and the Real-Time Workshop) to allocate global memory for
these output port signals. Hence this memory is only written to by your
S-function and persists between model execution steps.
Languages C
10-177
ssSetOutputPortSampleTime
Purpose 10ssSetOutputPortSampleTime
Specify the sample time of an output port.
Arguments S
SimStruct representing an S-function block.
outputPortIdx
Index of the output port whose sample time is being set.
period
Sample time of output port.
Languages C
10-178
ssSetOutputPortVectorDimension
Purpose 10ssSetOutputPortVectorDimension
Specify dimension information for an output port that emits vector signals.
Arguments S
SimStruct representing an S-function block.
port
Index of an output port
w
Width of vector or DYNAMICALLY_SIZED
Example The following example specifies that output port 0 emits an 8-element matrix
signal.
ssSetOutputPortVectorDimension(S, 0, 8);
Languages C
10-179
ssSetOutputPortWidth
Purpose 10ssSetOutputPortWidth
Specify the width of an output port.
Arguments S
SimStruct representing an S-function block.
port
Index of the output port whose width is being set.
width
Width of output port.
Languages Ada, C
10-180
ssSetParameterName
Purpose 10ssSetParameterName
Set the name of a parameter.
Arguments S
SimStruct representing an S-function block.
Parameter
Index of a parameter
Name
Name of the parameter
Languages Ada
10-181
ssSetParameterTunable
Purpose 10ssSetParameterTunable
Set the tunability of a parameter.
Arguments S
SimStruct representing an S-function block.
Parameter
Index of a parameter
IsTunable
true indicates that the parameter is tunable.
Languages Ada
10-182
ssSetPlacementGroup
Purpose 10ssSetPlacementGroup
Specify the name of the placement group of a block.
Arguments S
SimStruct representing an S-function block. The block must be either a source
block (i.e., a block without input ports) or a sink block (i.e., a block without
output ports).
groupName
Name of placement group name of the block represented by S.
Description Use this macro to specify the name of the placement group to which the block
represented by S belongs. S-functions that share the same placement group
name are placed adjacent to each other in the block execution order list for the
model. This macro should be invoked in mdlInitializeSizes.
Languages C
10-183
ssSetRunTimeParamInfo
Purpose 10ssSetRunTimeParamInfo
Specify the attributes of a run-time parameter.
Arguments S
SimStruct representing an S-function block.
param
Index of a run-time parameter
ssParamRec Structure
The simstruc.h macro defines this structure as follows.
typedef struct ssParamRec_tag {
const char *name;
int_T nDimensions;
int_T *dimensions;
DTypeId dataTypeId;
boolean_T complexSignal;
void *data;
const void *dataAttributes;
int_T nDlgParamIndices;
int_T *dlgParamIndices;
TransformedFlag transformed; /* Transformed status */
boolean_T outputAsMatrix; /* Write out parameter as a
vector (false)
* [default] or a matrix (true)
*/
} ssParamRec;
10-184
ssSetRunTimeParamInfo
dataTypeId. Data type of the parameter. For built-in data types, see
BuiltInDTypeId in simstruc_types.h.
10-185
ssSetRunTimeParamInfo
• RTPARAM_MAKE_TRANSFORMED_TUNABLE
Specifies that this run-time parameter corresponds to a single tunable dialog
parameter (nDialogParamIndices is one) and that the run-time parameter’s
value or data type differs from the dialog parameter’s. During code
generation, Real-Time Workshop writes the data type and value of the
run-time parameter (rather than the dialog parameter) out to the Real-Time
Workshop file. For example, suppose that the dialog parameter contains a
workspace variable, k, of type double and value 1. Further, suppose the
S-function sets the data type of the corresponding run-time variable to int8
and the run-time parameter’s value to 2. In this case, during code generation,
the Real-Time Workshop writes k out to the Real-Time Workshop file as an
int8 variable with an initial value of 2.
Languages C
10-186
ssSetSampleTime
Purpose 10ssSetSampleTime
Set the period of a sample time.
Arguments S
SimStruct representing an S-function block.
st_index
Index of sample time whose period is to be set.
period
Period of the sample time specified by st_index
Description Use this macro in mdlInitializeSizes to specify the “period” of the sample
time where st_index starts at 0.
Languages Ada, C
10-187
ssSetSFcnParamNotTunable
Purpose 10ssSetSFcnParamNotTunable
Make a block parameter untunable.
Arguments S
SimStruct representing an S-function block.
index
Index of parameter to be made untunable.
Languages C
10-188
ssSetSFcnParamTunable
Purpose 10ssSetSFcnParamTunable
Make a block parameter tunable.
Arguments S
SimStruct representing an S-function block.
param
Index of parameter
isTunable
Valid values are 1 (tunable) or 0 (not tunable)
Description Use this macro in mdlInitializeSizes to specify whether a user can change a
dialog parameter during the simulation. The parameter index starts at 0 and
is less than ssGetSFcnParamsCount(S). This improves efficiency and provide
errors handling in the event that an attempt is made to change the parameter.
Languages C
10-189
ssSetSolverNeedsReset
Purpose 10ssSetSolverNeedsReset
Ask Simulink to reset the solver.
Arguments S
SimStruct representing an S-function block or a Simulink model.
Description This macro causes the solver for the current simulation to reinitialize variable
step size and zero-crossing computations. This happens only if the solver is a
variable-step, continuous solver. (The macro has no effect if the user has
selected another type of solver for the current simulation.) An S-function
should invoke this macro whenever changes occur in the dynamics of the
S-function, e.g., a discontinuity in a state or output, that might invalidate the
solver’s step-size computations. Otherwise, the solver might take
unnecessarily small steps, slowing down the simulation.
Languages C
Example The following example uses this macro to ask Simulink to reset the solver.
static void mdlOutputs(SimStruct *S, int_T tid)
{
:
: <snip>
:
if ( under_certain_conditions ) {
double *x = ssGetContStates(S);
/* reset the states */
for (i=0; i<nContStates; i++) {
x[i] = 0.0;
}
/* Ask Simulink to reset the solver. */
ssSetSolverNeedsReset(S);
10-190
ssSetSolverNeedsReset
}
}
Also see the source code for the Time-Varying Continuous Transfer Function
(matlabroot/simulink/src/stvctf.c) for an example of where and how to use
this macro.
10-191
ssSetStopRequested
Purpose 10ssSetStopRequested
Set the simulation stop requested flag.
Arguments S
SimStruct representing an S-function block or a Simulink model.
val
Boolean value (int_T) specifying whether stopping the simulation has been
requested (1) or not (0).
Description Sets the simulation stop requested flag to val. If val is not zero, Simulink halts
the simulation at the end of the current time step.
Languages C
10-192
ssSetTNext
Purpose 10ssSetTNext
Set the time of the next sample hit.
Arguments S
SimStruct representing an S-function block
tnext
Time of the next sample hit
Description A discrete S-function with a variable sample time should use this macro in
mdlGetTimeOfNextVarHit to specify the time of the next sample hit.
Languages C
10-193
ssSetUserData
Purpose 10ssSetUserData
Specify user data.
Arguments S
SimStruct representing an S-function block.
data
User data
Languages C, C++
10-194
ssSetVectorMode
Purpose 10ssSetVectorMode
Specify the vector mode that an S-function supports.
Arguments S
SimStruct representing an S-function block.
mode
vector mode
Description Specifies the types of vector-like signals that an S-function block’s input and
output ports support. Simulink uses this information during signal dimension
propagation to check the validity of signals connected to the block or emitted
by the block. The enumerate type, ssVectorMode, defines the set of values that
mode can have.
SS_UNKNOWN_MODE Unknown
SS_1_D_OR_COL_VECT 1-D (vector) or single-column 2-D (column
vector)
SS_1_D_OR_ROW_VECT 1-D or single-row 2-D (row vector) signals
SS_1_D_ROW_OR_COL_VECT Vector or row or column vector
SS_1_D_VECT Vector
SS_COL_VECT Column vector
SS_ROW_VECT Row vector
Languages C
10-195
ssUpdateAllTunableParamsAsRunTimeParams
Purpose 10ssUpdateAllTunableParamsAsRunTimeParams
Updates the values of run-time parameters to be the same as those of the
corresponding tunable dialog parameters.
Arguments S
Languages C
10-196
ssUpdateRunTimeParamData
Purpose 10ssUpdateRunTimeParamData
Updates the value of a run-time parameter.
Arguments S
SimStruct representing an S-function block.
param
Index of a run-time parameter
data
New value of the parameter
Languages C
10-197
ssUpdateRunTimeParamInfo
Purpose 10ssUpdateRunTimeParamInfo
Updates the attributes of a run-time parameter.
Arguments S
SimStruct representing an S-function block.
param
Index of a run-time parameter
info
Attributes of the run-time parameter
Languages C
10-198
ssWarning
Purpose 10ssWarning
Display a warning message.
Arguments S
SimStruct representing an S-function block or a Simulink model.
msg
Warning message.
Description Displays msg. Expands to mexWarnMsgTxt when compiled for use with
Simulink. When compiled for use with the Real-Time Workshop, expands to
printf("Warning:%s from '%s'\n",msg, ssGetPath(S));, if the target has
stdio facilities; otherwise, it expands to a comment.
Languages C
10-199
ssWriteRTWMxVectParam
Purpose 10ssWriteRTWMxVectParam
Write a vector parameter in MATLAB format to the model.rtw file.
Arguments S
SimStruct representing an S-function block.
name
Parameter name
rValue
Real values of parameter
cValue
Complex values of parameter
dataType
Data type of parameter elements (see “Specifying Data Type Info” on
page 10-204)
size
Number of elements in vector
Description Use this function in mdlRTW to write a vector parameter in Simulink format to
this S-function’s model.rtw file. This function returns TRUE if successful.
Languages C
10-200
ssWriteRTWMx2dMatParam
Purpose 10ssWriteRTWMx2dMatParam
Write a matrix parameter in MATLAB format to the model.rtw file.
Arguments S
SimStruct representing an S-function block.
name
Parameter name
rValue
Real elements of parameter array
iValue
Imaginary elements of parameter array
dataType
Data type of parameter elements (see “Specifying Data Type Info” on
page 10-204)
nRows
Number of rows in matrix
nColumns
Number of columns in matrix
Description Use this function in mdlRTW to write a matrix parameter in MATLAB format to
this S-function’s model.rtw file. This function returns TRUE if successful.
Languages C
10-201
ssWriteRTWParameters
Purpose 10ssWriteRTWParameters
Write tunable parameter information to model.rtw file.
Arguments S
SimStruct representing an S-function block.
nParams
Number of tunable parameters
paramType
Type of parameter (see “Parameter Type-Specific Arguments”)
paramName
Name of parameter
stringInfo
General information about the parameter, such as how it was derived
...
Remaining arguments depend on parameter type (see “Parameter
Type-Specific Arguments”).
Description Use this function in mdlRTW to write tunable parameter information to this
S-function’s model.rtw file. Your S-function must write the parameters out in
the same order as they are declared at the beginning of the S-function. This
function returns TRUE if successful.
Note This function is provided for compatibility with S-functions that do not
use run-time parameters. It is suggested that you use run-time parameters
(see “Run-Time Parameters” on page 7-6). If you do use run-time parameters,
you do not need to use this function.
10-202
ssWriteRTWParameters
Argument Description
Argument Description
• SSWRITE_VALUE_DTYPE_2DMAT
Argument Description
• SSWRITE_VALUE_DTYPE_ML_VECT
Argument Description
10-203
ssWriteRTWParameters
Argument Description
• SSWRITE_VALUE_DTYPE_ML_2DMAT
Argument Description
10-204
ssWriteRTWParameters
Languages C
10-205
ssWriteRTWParamSettings
Purpose 10ssWriteRTWParamSettings
Write values of nontunable parameters to the model.rtw file.
Arguments S
SimStruct representing an S-function block.
nParamSettings
Number of parameter settings
settingType
Type of parameter (see “Parameter Setting Type-Specific Arguments”)
settingName
Name of parameter
...
Remaining arguments depend on parameter type (see “Parameter Setting
Type-Specific Arguments”).
Description Use this function in mdlRTW to write nontunable parameter setting information
to this S-function’s model.rtw file. A nontunable parameter is any parameter
that the S-function has declared as nontunable, using the
ssSetParameterTunable macro. You can also use this macro to write out other
constant values required to generate code for this S-function.
This function returns TRUE if successful.
Argument Description
10-206
ssWriteRTWParamSettings
Argument Description
Argument Description
• SSWRITE_VALUE_NUM (number)
Argument Description
Argument Description
Argument Description
10-207
ssWriteRTWParamSettings
Argument Description
Argument Description
Argument Description
Argument Description
10-208
ssWriteRTWParamSettings
Argument Description
Argument Description
Languages C
10-209
ssWriteRTWScalarParam
Purpose 10ssWriteRTWScalarParam
Write a scalar parameter to the model.rtw file.
Arguments S
SimStruct representing an S-function block.
name
Parameter name
value
Parameter value
type
Integer ID of the type of the parameter value, for example, the ID of one of
Simulink’s builtin datatypes (see BuiltInDTypeId in simstruc_types.h in
MATLAB’s simulink/include subdirectory) or the ID of a user-defined type
(see “Custom Data Types” on page 7-15).
Description Use this function in mdlRTW to write scalar parameters to this S-function’s
model.rtw file. This function returns TRUE if successful.
Languages C
10-210
ssWriteRTWStr
Purpose 10ssWriteRTWStr
Write a string to the model.rtw file.
Arguments S
SimStruct representing an S-function block.
str
String
Description Use this function in mdlRTW to write strings to this S-function’s model.rtw file.
This function returns TRUE if successful.
Languages C
10-211
ssWriteRTWStrParam
Purpose 10ssWriteRTWStrParam
Write a string parameter to the model.rtw file.
Arguments S
SimStruct representing an S-function block.
name
Parameter name
value
Parameter value
Description Use this function in mdlRTW to write string parameters to this S-function’s
model.rtw file. This function returns TRUE if successful.
Languages C
10-212
ssWriteRTWStrVectParam
Purpose 10ssWriteRTWStrVectParam
Write a string vector parameter to the model.rtw file.
Arguments S
SimStruct representing an S-function block.
name
Parameter name
value
Parameter values
size
Number of elements in vector
Description Use this function in mdlRTW to write a vector of string parameters to this
S-function’s model.rtw file. This function returns TRUE if successful.
Languages C
10-213
ssWriteRTWVectParam
Purpose 10ssWriteRTWVectParam
Write a vector parameter to the model.rtw file.
Arguments S
SimStruct representing an S-function block.
name
Parameter name
value
Parameter values
dataType
Data type of parameter elements (see “Specifying Data Type Info” on
page 10-204)
size
Number of elements in vector
Description Use this function in mdlRTW to write a vector parameter in Simulink format to
this S-function’s model.rtw file. This function returns TRUE if successful.
Languages C
10-214
ssWriteRTWWorkVect
Purpose 10ssWriteRTWWorkVect
Write work vectors to model.rtw file.
Arguments S
SimStruct representing an S-function block.
vectName
Name of work vector (must be “RWork”, “IWork” or “PWork”)
settingType
Type of parameter (see “Parameter Setting Type-Specific Arguments”)
name1 ... nameN
Names of groups of work vector elements
size1 ... sizeN
Size of each element group (the total of the sizes must equal the size of the work
vector
Description Use this function in mdlRTW to write work vectors to this S-function’s model.rtw
file. This function returns TRUE if successful.
Languages C
10-215
ssWriteRTW2dMatParam
Purpose 10ssWriteRTW2dMatParam
Write a matrix parameter to the model.rtw file.
Arguments S
SimStruct representing an S-function block.
name
Parameter name
value
Parameter values
dataType
Data type of parameter elements (see “Specifying Data Type Info” on
page 10-204)
nRows
Number of rows in matrix
nColumns
Number of columns in matrix
Description Use this function in mdlRTW to write a vector of numeric parameters to this
S-function’s model.rtw file. This function returns TRUE if successful.
Languages C
10-216
Index
A
additional parameters for S-functions 2-5 sample time for hybrid block 7-22
array bounds checking 7-33 variable step S-function (C MEX) 7-46
variable step S-function (M-file) 2-16
exception free code 7-31
B
block-based sample times 7-16
H
hybrid block, setting sample time 7-22
C hybrid system S-function example (C MEX) 7-42
C MEX S-functions 1-2, 4-1, 5-1, 6-1 hybrid system S-function example (M-file) 2-13
callback methods 1-9
continuous block, setting sample time 7-21
continuous state S-function example (C MEX) I
7-34 input arguments for M-file S-functions 2-6
continuous state S-function example (M-file) 2-8 inputs, dynamically sized 1-12
D M
direct feedthrough 1-11 masked multiport S-functions 7-13
direct index lookup table example 8-24 matrix.h 3-29
discrete state S-function example (C MEX) 7-38 mdlCheckParameters 9-3
discrete state S-function example (M-file) 2-11 mdlDerivatives 9-5
dynamically sized inputs 1-12 mdlGetTimeOfNextVarHit 9-6
mdlInitializeConditions 9-7
mdlInitializeSampleTimes 9-9
E mdlInitializeSizes 1-12, 2-4, 9-13
examples mdlOutput function 7-21
continuous state S-function (C MEX) 7-34 mdlOutputs 9-17
continuous state S-function (M-file) 2-8 mdlProcessParameters 9-18
direct index lookup table 8-24 mdlRTW 8-21, 9-20
discrete state S-function (C MEX) 7-38 mdlSetDefaultPortComplexSignals 9-21
discrete state S-function (M-file) 2-11 mdlSetDefaultPortDataTypes 9-22
hybrid system S-function (C MEX) 7-42 mdlSetDefaultPortDimensionInfo 9-23
hybrid system S-function (M-file) 2-13 mdlSetInputPortComplexSignal 9-24
pointer work vector 7-26 mdlSetInputPortDataType 9-25
sample time for continuous block 7-21 mdlSetInputPortDimensionInfo 9-26
I-1
Index
mdlSetInputPortFrameData 9-28 S
mdlSetInputPortSampleTime 9-29 S_FUNCTION_LEVEL 2, #define 3-28
mdlSetInputPortWidth 9-31 S_FUNCTION_NAME, #define 3-28
mdlSetOutputPortComplexSignal 9-32 sample times
mdlSetOutputPortDataType 9-33 block-based 7-16
mdlSetOutputPortDimensionInfo 9-34 continuous block, example 7-21
mdlSetOutputPortSampleTime 9-36 hybrid block, example 7-22
mdlSetOutputPortWidth 9-37 port-based 7-19
mdlSetWorkWidths 9-38 S-Function block 1-2
mdlStart 9-39 multirate 7-21
mdlTerminate 9-40 S-Function Builder 3-5
mdlUpdate 7-21, 9-41 S-function options 10-167
mdlZeroCrossings 9-42 S-function routines 1-8
memory and work vectors 7-24 M-file 2-2
mex utility 1-2 S-functions
mex.h 3-29 additional parameters 2-5
M-file S-function routines 2-2 C MEX 1-2, 4-1, 5-1, 6-1
mixedm.c example 7-42 definition 1-2
multirate S-Function blocks 7-21 direct feedthrough 1-11
exception free code 7-31
inlined 8-7, 8-19
O input arguments for M-files 2-6
options, S-function 10-167 masked multiport 7-13
parameter field 7-3
purpose 1-5
P routines 1-8
parameters run-time routines 7-32
passing to S-functions 1-3 types of 8-3
parameters, S-function 2-5 using in models 1-2
penddemo demo 1-5 when to use 1-5
pointer work vector, example 7-26 wrapper 8-9
port-based sample times 7-19 sfuntmpl.c template 3-28
simsizes function 2-4
simulation loop 1-6
R simulation stages 1-6
re-entrancy 7-24
simulink.c 3-30
run-time routines 7-32
sizes structure 1-12, 2-4
I-2
Index
I-3
Index
ssSetDWorkUsedAsDState 10-132
ssSetDWorkWidth 10-133
ssSetErrorStatus 10-134
ssSetExternalModeFcn 10-16, 10-135
ssSetInputPortDimensionInfo 10-138
ssSetInputPortDirectFeedThrough 10-141
ssSetInputPortFrameData 10-140
ssSetInputPortOffsetTime 10-143
ssSetInputPortRequiredContiguous 10-50,
10-147
ssSetInputPortReusable 10-145
ssSetInputPortSampleTime 10-148
ssSetInputPortSampleTimeIndex 10-149
ssSetModeVectorValue 10-152
ssSetNumDWork 10-155
ssSetNumNonsampledZCs 10-159
ssSetNumSFcnParams 10-165
ssSetSFcnParamNotTunable 10-188
ssSetUserData 10-194
synchronizing multirate S-Function blocks 7-22
T
tmwtypes.h 3-29
V
variable step S-function example (C MEX) 7-46
variable step S-function example (M-file) 2-16
W
work vectors 7-24
I-4