Documentation

Test Generated Code Using Software-in-the-Loop (SIL) and Processor-in-the-Loop (PIL) Simulation

This example shows how you can use the SIL or PIL simulation mode to test generated production code. With SIL simulation, you test source code on your host computer. With PIL simulation, you test the compiled object code that you intend to deploy in production by running the object code on real target hardware or an instruction set simulator. You can compare the SIL or PIL results with normal mode results. You can also collect execution time measurements.

Select the approach for SIL or PIL testing that best fits your needs. To help with this choice, consider these questions about your task:

  • For which model component and code interface will you test the generated code?

    * A top-model (standalone code interface)
    * A subsystem (right-click build and standalone code
        interface)
    * A referenced model (model reference code interface)

  • How will you apply input stimulus signals or test vectors to your component under test?

    * Load stimulus data from the MATLAB(R) workspace or from a
        MATLAB(R) script
    * Use a test harness model (or a system model) to generate
        stimulus data

  • Is it important to rapidly switch between normal, SIL, or PIL simulation mode without making changes to your model?

    * Yes - it must be easy to switch simulation mode simply by
        choosing from a menu selection
    * No - it is acceptable to change the model and insert a
        special block to represent a component running in SIL or PIL
        mode

  • If you intend to test object code executing in the target environment (real hardware or instruction set simulator), which of the following options apply to your situation?

    * The products from MathWorks(R) support your compiler and
        target environment
    * There is a third party, off-the-shelf PIL configuration for
        your target environment
    * You will use the documented API to implement a connectivity
        configuration that supports your target environment

Study the examples below to help you determine the right approach for your situation. See also Create a Target Communication Channel for Processor-in-the-Loop (PIL) Simulation and Configure Processor-in-the-Loop (PIL) for a Custom Target.

Example 1: SIL or PIL Block Simulation for Subsystems

This example shows how you can use the SIL block for testing generated code. With this approach:

  • You can test code generated for subsystems or top models. The generated code uses the standalone code interface.

  • You provide a test harness or a system model to supply test vector or stimulus inputs

  • You replace your original subsystem with the generated SIL block. To avoid losing your original subsystem, do not save your model in this state.

Open a simple model, which consists of a control algorithm connected to a plant model in a closed loop. The control algorithm regulates the output from the plant.

model='rtwdemo_sil_block';
close_system(model,0)
open_system(model)
out = sim(model,10);
yout_normal = find(out,'yout');
clear out

Configure the build process to create the SIL block for testing.

set_param(model,'CreateSILPILBlock','SIL');

If you need to verify the behavior on production hardware, specify a PIL block.

To create the SIL block, generate code for the control algorithm subsystem. You see the SIL block at the end of the build process. Its input and output ports match those of the control algorithm subsystem.

close_system('untitled',0);
rtwbuild([model '/Controller'])
### Starting build procedure for model: Controller
### Creating SIL block ...
Building with 'gcc'.
MEX completed successfully.
### Successful completion of build procedure for model: Controller

Alternatively, you can right-click the subsystem and select C/C++ Code > Build This Subsystem. In the dialog box that opens, click Build.

To perform a SIL simulation of the controller and plant model in a closed loop, replace the original control algorithm with the new SIL block.

controllerBlock = [model '/Controller'];
blockPosition = get_param(controllerBlock,'Position');
delete_block(controllerBlock);
add_block('untitled/Controller',[controllerBlock '(SIL)'],...
          'Position', blockPosition);
close_system('untitled',0);
clear controllerBlock blockPosition

Run the SIL simulation.

out = sim(model,10);
### Preparing to start SIL block simulation: <a href="matlab: targets_hyperlink_manager('run',1);">rtwdemo_sil_block/Controller(SIL)</a> ...
### Starting SIL simulation for component: rtwdemo_sil_block/Controller
### Stopping SIL simulation for component: rtwdemo_sil_block/Controller

The control algorithm uses single-precision, floating-point arithmetic. You can expect the order of magnitude for differences between SIL and normal simulations to be close to the machine precision for single-precision data.

Define an error tolerance for SIL simulation results that is based on the machine precision for the single-precision, normal simulation results.

machine_precision = eps(single(yout_normal));
tolerance = 4 * machine_precision;

Compare SIL and normal simulation results.

yout_sil = find(out,'yout');
tout = find(out,'tout');
fig1 = figure;
subplot(3,1,1), plot(yout_normal), title('Controller output for normal simulation')
subplot(3,1,2), plot(tout, [abs(yout_normal-yout_sil) tolerance]), ...
    title('Error and error tolerance threshold')
subplot(3,1,3), plot(yout_sil), title('Controller output for SIL simulation');

Clean up.

close_system(model,0);
if ishandle(fig1), close(fig1), end
clear fig1
simResults={'out','yout_sil','yout_normal','tout','machine_precision'};
save([model '_results'],simResults{:});
clear(simResults{:},'simResults')

Example 2: SIL or PIL Simulation for Model Blocks

This example shows how you can test generated model code by using a test harness model to run a Model block SIL simulation.

With this approach:

  • You verify code generated for top models (standalone code interface) or referenced models (model reference code interface). See Referenced Model Simulation Using SIL or PIL.

  • You use a test harness model or a system model to provide test vector or stimulus inputs.

  • You can easily switch a Model block between the normal, SIL and PIL simulation modes.

To run a PIL simulation, you require a target connectivity configuration. The target connectivity configuration enables the PIL simulation to:

  • Build the target application.

  • Download, start, and stop the application on the target.

  • Support communication between Simulink and the target.

Open an example model that has two Model blocks which reference the same model. One Model block is configured to run in SIL mode. The other Model block is configured to run in normal mode.

model='rtwdemo_sil_modelblock';
open_system(model);

Switch off code coverage.

coverageSettings = get_param(model, 'CodeCoverageSettings');
coverageSettings.CoverageTool='None';
set_param(model, 'CodeCoverageSettings',coverageSettings);

Simulate Model to Test Top-Model Code

For the Model block in SIL mode, specify generation of top-model code (standalone code interface).

set_param([model '/CounterA'], 'CodeInterface', 'Top model');

Run a top-model simulation.

out = sim(model,20);
### Successfully updated the model reference SIM target for model: rtwdemo_sil_counter
### Starting build procedure for model: rtwdemo_sil_counter
### Successful completion of build procedure for model: rtwdemo_sil_counter
### Preparing to start SIL simulation ...
Building with 'gcc'.
MEX completed successfully.
### Updating code generation report with SIL files ...
### Starting SIL simulation for component: rtwdemo_sil_counter
### Stopping SIL simulation for component: rtwdemo_sil_counter

The model block in SIL mode runs as a separate process on your computer. In the working folder, you see that standalone code is generated for the referenced model (unless generated code from a previous build exists).

Compare the behavior of Model blocks in normal and SIL modes. Observe that the results match.

yout = find(out,'logsOut');
yout_sil = yout.get('counterA').Values.Data;
yout_normal = yout.get('counterB').Values.Data;
fig1 = figure;
subplot(3,1,1), plot(yout_normal), title('Counter output for normal simulation')
subplot(3,1,2), plot(yout_normal-yout_sil), title('Error')
subplot(3,1,3), plot(yout_sil), title('Counter output for Model block SIL (top model) simulation');

Simulate Model to Test Model Reference Code

For the Model block in SIL mode, specify generation of referenced model code (model reference code interface).

set_param([model '/CounterA'], 'CodeInterface', 'Model reference');

Run a top-model simulation.

out2 = sim(model,20);
### Starting build procedure for model: rtwdemo_sil_counter
### Successful completion of build procedure for model: rtwdemo_sil_counter
### Preparing to start SIL simulation ...
Building with 'gcc'.
MEX completed successfully.
### Updating code generation report with SIL files ...
### Starting SIL simulation for component: rtwdemo_sil_counter
### Stopping SIL simulation for component: rtwdemo_sil_counter

The model block in SIL mode runs as a separate process on your computer. In the working folder, you see that model reference code is generated (unless code from a previous build exists).

Compare the behavior of Model blocks in normal and SIL modes. Observe that the results match.

yout2 = find(out2,'logsOut');
yout2_sil = yout2.get('counterA').Values.Data;
yout2_normal = yout2.get('counterB').Values.Data;
fig2 = figure;
subplot(3,1,1), plot(yout2_normal), title('Counter output for normal simulation')
subplot(3,1,2), plot(yout2_normal-yout2_sil), title('Error')
subplot(3,1,3), plot(yout2_sil), title('Counter output for Model block SIL (model reference) simulation');

Clean up.

close_system(model,0);
if ishandle(fig1), close(fig1), end, clear fig1
if ishandle(fig2), close(fig2), end, clear fig2
simResults={'out','yout','yout_sil','yout_normal', ...
            'out2','yout2','yout2_sil','yout2_normal', ...
            'SilCounterBus','T','reset','ticks_to_count','Increment'};
save([model '_results'],simResults{:});
clear(simResults{:},'simResults')

Example 3: SIL or PIL Simulation for Top Models

This example shows how you can test generated code for a model by running a top-model SIL or PIL simulation.

With this approach:

  • You verify code generated for a top model (standalone code interface).

  • You configure the model to load test vectors or stimulus inputs from the MATLAB® workspace.

  • You can easily switch the top model between the normal, SIL, and PIL simulation modes. To run a PIL simulation, you require a target connectivity configuration. See Example 2.

Open a simple counter top model.

model='rtwdemo_sil_topmodel';
close_system(model,0)
open_system(model)

Turn off collection and reporting of model coverage data.

set_param(gcs, 'RecordCoverage','off')

Configure the input stimulus data.

[ticks_to_count, reset, counter_mode, count_enable] = ...
    rtwdemo_sil_topmodel_data(T);

Configure logging options in the model.

set_param(model, 'LoadExternalInput','on');
set_param(model, 'ExternalInput','ticks_to_count, reset, counter_mode, count_enable');
set_param(model, 'SignalLogging', 'on');
set_param(model, 'SignalLoggingName', 'logsOut');

Enable execution time profiling.

set_param(model, 'CodeExecutionProfiling','on');
set_param(model, 'CodeProfilingInstrumentation','on');
set_param(model, 'CodeProfilingSaveOptions','AllData');

Switch off code coverage.

coverageSettings = get_param(model, 'CodeCoverageSettings');
coverageSettings.CoverageTool='None';
set_param(model, 'CodeCoverageSettings',coverageSettings);

Run a normal mode mode simulation.

set_param(model,'SimulationMode','normal')
[~, ~, yout_normal] = sim(model,10);

Run a top-model SIL simulation.

set_param(model,'SimulationMode','Software-in-the-Loop (SIL)')
[~, ~, yout_sil] = sim(model,10);
### Starting build procedure for model: rtwdemo_sil_topmodel
### Successful completion of build procedure for model: rtwdemo_sil_topmodel
### Preparing to start SIL simulation ...
Building with 'gcc'.
MEX completed successfully.
### Updating code generation report with SIL files ...
### Starting SIL simulation for component: rtwdemo_sil_topmodel
### Stopping SIL simulation for component: rtwdemo_sil_topmodel

Unless up-to-date code for this model exists, new code is generated and compiled. The generated code runs as a separate process on your host computer.

Plot and compare the results of the normal and SIL simulations. Observe that the results match.

fig1 = figure;
subplot(3,1,1), plot(yout_normal), title('Counter output for normal simulation')
subplot(3,1,2), plot(yout_normal-yout_sil), title('Error')
subplot(3,1,3), plot(yout_sil), title('Counter output for SIL simulation');

Clean up.

close_system(model,0);
if ishandle(fig1), close(fig1), end, clear fig1
simResults = {'yout_sil','yout_normal','model','T',...
              'ticks_to_count','reset'};
save([model '_results'],simResults{:}, 'executionProfile');
clear(simResults{:},'simResults')

Execution Time Measurements

In Example 3, you configured the model to collect execution time measurements and saved this data as a variable in the base workspace. The software provides an API to retrieve execution time information from the base workspace variable. For example, you can use the report method to create a summary report.

report(executionProfile);

For more information, see View and Compare Code Execution Times.

Clean up execution profiling data.

clear executionProfile

Further Information on Hardware Implementation Settings for SIL Simulation

When you run a SIL simulation, you must configure your hardware implementation settings (i.e. characteristics such as native word sizes) to allow compilation for your host computer. The settings can differ from the hardware implementation settings that you use when building the model for your production hardware. To avoid the need to change hardware implementation settings between SIL and PIL simulations, enable portable word sizes. For more information, see Configure Hardware Settings for Software-in-the-Loop (SIL) Simulation.

Was this topic helpful?