MATLAB Examples

Using Code Generation Verification API

Configure and run normal, software-in-the-loop (SIL), and processor-in-the-loop (PIL) simulations, and compare results.

Note: Simulink Test is a separate product that provides additional capabilities for SIL and PIL testing, for example, test sequence construction and test management.


Review the Model

The rtwdemo_cgv model uses buses, scalars, and vectorized data, plus error injection to create differences between test executions.

Note: Before executing the code in this example, change to a writable folder. If you are not working in a writable folder, code generation errors occur.

To open rtwdemo_cgv, in the MATLAB® Command Window, enter the following commands.

baseVars = who;  % For future cleanup.
cgvModel = 'rtwdemo_cgv';
open_system( cgvModel);

The model contains a hierarchical bus with three nested buses. This arrangement of buses produces complex hierarchical data at the first logged outport. At the second outport, the model injects errors in the signal at fixed intervals. These errors produce different results between two runs. The signal at the third outport is a vector of four values per sample to help show the comparison support.

Verify the Model Configuration

CGV provides a class, cgv.Config, to check whether models have a configuration that is compatible with execution in a SIL or PIL environment using an ert target. This model has already been modified using the cgv.Config class.

Execute Under CGV

Run in Normal and SIL Modes

The model executes in three modes under CGV: normal, SIL, and PIL. In each case, the CGV object captures the output data and writes it to a file. For more information, see CGV Documentation. To execute the model in normal and SIL simulation modes, enter:

cgvSim = cgv.CGV( cgvModel, 'Connectivity', 'Normal');
cgvSim.addInputData(1, [cgvModel '_data']);
% This next CGV function, addPostLoadFiles(), allows you to specify MATLAB(R)
% programs to execute, or mat-files to load, before execution of the model.
cgvSim.addPostLoadFiles({[cgvModel '_init.m']});
cgvSim.activateConfigSet( 'CS1_default');
result1 =;

% CGV provides methods to simplify numerical equivalence checking.
% The copySetup method creates an exact duplicate of an existing CGV object without
% results data.  You can change the SimulationMode using setMode() and then
% execute again.
cgvSil = cgvSim.copySetup();
cgvSil.setMode( 'SIL');
% You can provide a baseline file to CGV for comparing the simulation
% output. In this example, the comparison results set the status to
% 'failed', because the ErrorsInjected signal differs between simulations.
cgvSil.addBaseline( 1, 'rtwdemo_cgv_results');
result2 =;

% To see the name(s) of the signal(s) that did match, use getMismatches.
% Mismatched signal names are only available if a baseline was added and
% the comparison failed.
if strcmp( cgvSil.getStatus( 1), 'failed')
    disp( 'Mismatched Signal Names:');
    [signalNames, plotFiles] = cgvSil.getMismatches( 1);
    fprintf( 1, 'Signal Names: %s\n', signalNames{:} );
    fprintf( 1, 'Path to plot files: %s\n', plotFiles{:});
    assert(numel(signalNames)==1,'Expected exactly one mismatch');
Applying Configuration Set:
Applying PostLoad file:
Starting execution:
  ComponentType: topmodel
  Connectivity: normal
End CGV execution: status completed.
Applying PostLoad file:
Starting execution:
  ComponentType: topmodel
  Connectivity: sil
### Starting build procedure for model: rtwdemo_cgv
### Successful completion of build procedure for model: rtwdemo_cgv
### Preparing to start SIL simulation ...
Building with 'Xcode with Clang'.
MEX completed successfully.
### Updating code generation report with SIL files ...
### Starting SIL simulation for component: rtwdemo_cgv
### Stopping SIL simulation for component: rtwdemo_cgv
End CGV execution: status failed.
Mismatched Signal Names:
Signal Names: simout.getElement(3).Values.Data
Path to plot files: /private/tmp/Bdoc17b_685977_71560/publish_examples3/tp46294982/ex96023632/cgv_output/input_1_figure_1.png

Run in PIL Mode

Next, the model runs a PIL simulation, using your embedded processor. A universal embedded processor does not exist. Therefore, PIL support is provided by using the host computer where MATLAB® is running. The host processor is treated as an embedded target.

A customization file is executed that maps this model's PIL execution onto the SIL infrastructure. After the customization file is executed, CGV execution displays PIL messages for the mode. SIL messages display the connectivity target.

The configuration set for the model is already configured with: Hardware Implementation > Test hardware > Test hardware is the same as production hardware is checked. Code Generation > Verification > Enable portable word sizes is checked. These settings work in SIL and in PIL when PIL is mapped onto the SIL connectivity target.

copyfile( which( 'rtwdemo_cgv_sl_customization.m'), fullfile( pwd, 'sl_customization.m'),'f');

cgvPil = cgvSim.copySetup();
cgvPil.setMode( 'PIL');
result3 =;
Applying PostLoad file:
Starting execution:
  ComponentType: topmodel
  Connectivity: pil
### Starting build procedure for model: rtwdemo_cgv
### Successful completion of build procedure for model: rtwdemo_cgv
### Preparing to start PIL simulation ...
Building with 'Xcode with Clang'.
MEX completed successfully.
### Connectivity configuration for "/private/tmp/Bdoc17b_685977_71560/publish_examples3/tp46294982/ex96023632/rtwdemo_cgv_ert_rtw": CS1_default ###
### Updating code generation report with PIL files ...
### Starting application: 'rtwdemo_cgv_ert_rtw/pil/rtwdemo_cgv'
End CGV execution: status completed.

Remove Customization

To prevent problems with other models, immediately remove the customization used to show PIL mode.

delete( 'sl_customization.m');

Check that execution did not terminate with an error

The run() function returns a Boolean value, which is true if the execution completes without model compilation or simulation error. Before accessing the data, check the result returned from each execution.

if ~result1 || ~result2 || ~result3
    disp('Execution of model failed.');

simData   = cgvSim.getOutputData(1);
silData   = cgvSil.getOutputData(1);
pilData   = cgvPil.getOutputData(1);

Compare Results

The executions are now complete. Compare the results. The comparison code supports a plot with filters. Plots display both the data and the difference.

CGV functions display signals names (as used in the command window) and create a file correlating tolerance information with signal names.

Show Signal Names from Normal Simulation

Display a list of signal names from the saved data.

Note: ignores signals that appear in only one data set. For example, the compare function ignores a logged internal signal hi0 that appears in the output of a normal simulation, but does not appear in the output of a SIL simulation.

cgv.CGV.getSavedSignals( simData);

Create a Tolerance File

The CGV createToleranceFile function creates a file correlating tolerance information with signal names. For the options available to configure tolerances, see cgv.CGV.createToleranceFile. By default, tolerances are zero. Therefore the signals must match exactly. This example allows a delta of 0.5 on the ErrorsInjected signal.

signalList = {'simData.ErrorsInjected.Data' };
toleranceList = { { 'absolute', 0.5}};
cgv.CGV.createToleranceFile( 'localtol', signalList, toleranceList );

Compare Signals

By default, the function looks at signals that have a common name between both executions. In the following code, the simData.hi0.Data signals are not compared, because the signals do not appear in silData.

The second and fourth return parameters of the compare function are for matched figures and mismatched figures. Tildes (~) represent these parameters because this example does not use the return values.

A plot results from the mismatch on signal simData.ErrorsInjected.Data.

[matchNames, ~, mismatchNames, ~] = ... simData, silData, 'Plot', 'mismatch', ...
    'Tolerancefile', 'localtol');
fprintf( '%d Signals match, %d Signals mismatch\n', ...
    length(matchNames), length(mismatchNames));
assert(length(mismatchNames) == 1,'Expected exactly one mismatch');
assert(length(matchNames) == 14, 'Expected exactly 14 matches');

disp( 'Mismatched Signal Names:');
14 Signals match, 1 Signals mismatch
Mismatched Signal Names:

Compare Individual Signals

The function also compares only the specified signals. In this example, the function compares only three signals.

[matchNames, ~, mismatchNames, ~ ] = ... simData, silData, 'Plot', 'mismatch', ...
    'Signals', {'simData.getElement(3).Values.hi1.mid0.lo1.Data', 'simData.getElement(3).Values.hi1.mid0.lo2.Data', ...
fprintf( '%d Signals match, %d Signals mismatch\n', ...
    length(matchNames), length(mismatchNames));
assert(isempty(mismatchNames),'Expected no mismatches');
if ~isempty(mismatchNames)
    disp( 'Mismatched Signal Names:');

% Since a mismatch does not occur for these signals, a plot is not generated.
3 Signals match, 0 Signals mismatch

Additional Plotting Support

To create a plot of a list of signals, call cgv.CGV.plot. For example,

[signalNames, signalFigures] = cgv.CGV.plot( simData, ...
    'Signals', {'simData.getElement(2).Values.Data(:,1)'});

View Signal Data in the Simulation Data Inspector Tool

To open the Simulation Data Inspector tool, at the MATLAB® command line, enter Simulink.sdi.view. To import the signal data, in the Simulation Data Inspector tool, select File > Import Data, which opens the Data Import tool. Select Import from > Base workspace, to view and select the signals saved in simData and silData.

Clear Your Workspace

Clear the variables from the workspace:

newBaseVars = who;
addedVars = setdiff( newBaseVars, baseVars);
clearCmd = ['clear ' sprintf( '%s ', addedVars{:})];
eval( clearCmd);
clear newBaseVars addedVars clearCmd