Use DWork Vectors in S-Functions
What is a DWork Vector?
DWork vectors are blocks of memory that an S-function asks the Simulink® engine to allocate to each instance of the S-function in a model. If multiple instances of your S-function can occur in a model, your S-function must use DWork vectors instead of global or static memory to store instance-specific values of S-function variables. Otherwise, your S-function runs the risk of one instance overwriting data needed by another instance, causing a simulation to fail or produce incorrect results. The ability to keep track of multiple instances of an S-function is called reentrancy.
You can create an S-function that is reentrant by using DWork vectors that the engine manages for each particular instance of the S-function.
DWork vectors have several advantages:
Provide instance-specific storage for block variables
Support floating-point, integer, pointer, and general data types
Eliminate static and global variables
Interact directly with the Simulink engine to perform memory allocation, initialization, and deallocation
Facilitate inlining the S-function during code generation
Provide more control over how data appears in the generated code
Note
DWork vectors are the most generalized and versatile type of work vector and the following sections focus on their use. The Simulink product provides additional elementary types of work vectors that support floating-point, integer, pointer, and mode data. You can find a discussion of these work vectors in Elementary Work Vectors.
DWork vectors provide the most flexibility for setting data types, names, etc., of the data in the simulation and during code generation. The following list describes all the properties that you can set on a DWork vector:
Data type
Size
Numeric type, either real or complex
Name
Usage type (see Types of DWork Vectors)
Simulink Coder™ identifier
Simulink Coder storage class
Simulink Coder C type qualifier
See How to Use DWork Vectors for instructions on how to set these properties. The three Simulink Coder properties pertain only to code generation and have no effect during simulation.
How to Use DWork Vectors in Level-2 MATLAB S-Functions
Using DWork Vectors in Level-2 MATLAB S-Functions
The following steps show how to initialize and use DWork vectors in Level-2
MATLAB® S-functions. These steps use the S-function msfcn_unit_delay.m
.
In the
PostPropagationSetup
method, initialize the number of DWork vectors and the attributes of each vector. For example, the followingPostPropagationSetup
callback method configures one DWork vector used to store a discrete state.function PostPropagationSetup(block) %% Setup Dwork block.NumDworks = 1; block.Dwork(1).Name = 'x0'; block.Dwork(1).Dimensions = 1; block.Dwork(1).DatatypeID = 0; block.Dwork(1).Complexity = 'Real'; block.Dwork(1).UsedAsDiscState = true;
The reference pages for
Simulink.BlockCompDworkData
and the parent classSimulink.BlockData
list the properties you can set for Level-2 MATLAB S-function DWork vectors.Initialize the DWork vector values in either the
Start
orInitializeConditions
methods. Use theStart
method for values that are initialized only at the beginning of the simulation. Use theInitializeConditions
method for values that need to be reinitialized whenever a disabled subsystem containing the S-function is reenabled.For example, the following
InitializeConditions
method initializes the value of the DWork vector configured in the previous step to the value of the first S-function dialog parameter.function InitializeConditions(block) %% Initialize Dwork block.Dwork(1).Data = block.DialogPrm(1).Data;
In the
Outputs
,Update
, etc. methods, use or update the DWork vector values, as needed. For example, the followingOutputs
method sets the S-function output equal to the value stored in the DWork vector. TheUpdate
method then changes the DWork vector value to the current value of the first S-function input port.%% Outputs callback method function Outputs(block) block.OutputPort(1).Data = block.Dwork(1).Data; %% Update callback method function Update(block) block.Dwork(1).Data = block.InputPort(1).Data;
Note
Level-2 MATLAB S-functions do not support MATLAB sparse matrices. Therefore, you cannot assign a sparse matrix to the value of a DWork vector. For example, the following line of code produces an error
block.Dwork(1).Data = speye(10);
where the speye
command produces a sparse identity
matrix.
Level-2 MATLAB S-Function DWork Vector Example
The example S-function msfcn_varpulse.m
models a variable width pulse generator. The
S-function uses two DWork vectors. The first DWork vector stores the pulse width
value, which is modified at every major time step in the Update
method. The second DWork vector stores the handle of the pulse generator block in
the Simulink model. The value of this DWork vector does not change over the course
of the simulation.
The PostPropagationSetup
method, called
DoPostPropSetup
in this S-function, sets up the two DWork
vectors.
function DoPostPropSetup(block) % Initialize the Dwork vector block.NumDworks = 2; % Dwork(1) stores the value of the next pulse width block.Dwork(1).Name = 'x1'; block.Dwork(1).Dimensions = 1; block.Dwork(1).DatatypeID = 0; % double block.Dwork(1).Complexity = 'Real'; % real block.Dwork(1).UsedAsDiscState = true; % Dwork(2) stores the handle of the Pulse Geneator block block.Dwork(2).Name = 'BlockHandle'; block.Dwork(2).Dimensions = 1; block.Dwork(2).DatatypeID = 0; % double block.Dwork(2).Complexity = 'Real'; % real block.Dwork(2).UsedAsDiscState = false;
The Start
method initializes the DWork vector values.
function Start(block) % Populate the Dwork vector block.Dwork(1).Data = 0; % Obtain the Pulse Generator block handle pulseGen = find_system(gcs,'BlockType','DiscretePulseGenerator'); blockH = get_param(pulseGen{1},'Handle'); block.Dwork(2).Data = blockH;
The Outputs
method uses the handle stored in the second DWork
vector to update the pulse width of the Pulse Generator block.
function Outputs(block) % Update the pulse width value set_param(block.Dwork(2).Data, 'PulseWidth', num2str(block.InputPort(1).data));
The Update
method then modifies the first DWork vector with the
next value for the pulse width, specified by the input signal to the S-Function
block.
function Update(block) % Store the input value in the Dwork(1) block.Dwork(1).Data = block.InputPort(1).Data; %endfunction
See Also
Level-2 MATLAB S-Function | S-Function Builder | S-Function | MATLAB Function