MATLAB Examples

Integrate Generated Code Using Cross-Release Workflow

This example shows how to reuse previously generated code by creating a cross-release software-in-the-loop (SIL) block and incorporating the block within an integration model. For more information about the workflow, see docid:ecoder_ug.bvdzn2t.

Contents

Generate Code from a Model

In the cross-release code integration workflow, you create a software-in-the-loop (SIL) or processor-in-the-loop (PIL) block from code that you previously generated. The release that you used to generate the code can be a previous release or the current release.

To generate the code in a previous release, use File -> Export Model to -> Previous Version to save the model in the format of the previous release. Then, in the previous release, open the saved model and generate code.

This example uses the current release to generate code for a SIL block. Open the model and generate code.

model = 'rtwdemo_crossrelease_counter';
close_system(model,0)
load_system(model)
set_param(model, 'SimulationCommand', 'update');
open_system(model)
rtwbuild(model);
### Starting build procedure for model: rtwdemo_crossrelease_counter
### Successful completion of code generation for model: rtwdemo_crossrelease_counter

Export Code

To export code, use crossReleaseExport. The function generates cross-release code artifacts from the build folder that contains the previously generated code. If the generated code is from a previous release, crossReleaseExport starts the previous release. To manage the location of previous MATLAB versions for cross-release code integration, use the sharedCodeMATLABVersions function.

buildFolder = RTW.getBuildDir(model).BuildDirectory;
artifactsLocation = crossReleaseExport(buildFolder);

Manage Shared Code

Add the generated shared source code files to a repository folder that is used by the integration model.

sharedCodeRepo = 'SharedCodeRepo';
mkdir(sharedCodeRepo);
previousSharedCodeFolder = RTW.getBuildDir(model).SharedUtilsTgtDir;
sharedCodeUpdate(previousSharedCodeFolder, sharedCodeRepo, 'Interactive', false);
The following files will be copied from slprj/ert/_sharedutils to SharedCodeRepo/R2017b:

    rtwtypes.h

    rtwtypes.h
Files copied from slprj/ert/_sharedutils to SharedCodeRepo/R2017b.

Import Code

Open the integration model.

integrationModel = 'rtwdemo_crossrelease_integration';
close_system(integrationModel, 0);
load_system(integrationModel);

Modify the Simulink configuration set so that it references the existing shared code library.

cs = getActiveConfigSet(integrationModel);
set_param(cs, 'ExistingSharedCode', fullfile(pwd, sharedCodeRepo));

Create the cross-release SIL block.

blockHandle = crossReleaseImport(artifactsLocation, cs, 'SimulationMode', 'SIL');
### Starting import process for component: rtwdemo_crossrelease_counter_R2017b
### Starting build process for SIL block: rtwdemo_crossrelease_counter_R2017b

Incorporate Cross-Release SIL Block into Integration Model

To replace a block in the integration model with the cross-release block, use pil_block_replace. This function preserves the block size, line connections, and priority.

srcBlock = getfullname(blockHandle);
dstBlock = [integrationModel, '/', 'Counter'];
pil_block_replace(srcBlock, dstBlock)
open_system(integrationModel)
Successfully swapped the following blocks: 

untitled/rtwdemo_crossrelease_counter_R2017b_sil
rtwdemo_crossrelease_integration/Counter


Simulate Integration Model

Run a simulation of the integration model.

sim(integrationModel)
### Preparing to start SIL block simulation: rtwdemo_crossrelease_integration/Counter ...
### Starting SIL simulation for component: rtwdemo_crossrelease_counter_R2017b_sil
rtw.connectivity.HostLauncher: started executable with host process identifier 59252
rtw.connectivity.HostLauncher: stopped executable with host process identifier 59252
### Stopping SIL simulation for component: rtwdemo_crossrelease_counter_R2017b_sil

Tune Parameters

The source model for the cross-release SIL block references two tunable parameters, which are controlled by Simulink.Parameter objects in the base workspace. You can modify the behavior of the SIL simulation with these parameters.

countUpper.Value = 30;
countLower.Value = 20;
yout_retuned = sim(integrationModel, 'ReturnWorkspaceOutputs', 'on');
### Preparing to start SIL block simulation: rtwdemo_crossrelease_integration/Counter ...
### Starting SIL simulation for component: rtwdemo_crossrelease_counter_R2017b_sil
rtw.connectivity.HostLauncher: started executable with host process identifier 59464
rtw.connectivity.HostLauncher: stopped executable with host process identifier 59464
### Stopping SIL simulation for component: rtwdemo_crossrelease_counter_R2017b_sil

Configure Storage Class for Signals in Integration Model

Configure:

  • Signal names in the integration model to match the names used in the imported code.
  • Complementary storage classes.

In this case, the ticks input and count output are implemented through the ImportedExtern storage class in the imported code. If the storage class for the signals connected to the input and output ports of the cross-release block in the integration model is ExportedGlobal, the integration model must provide the definitions for the variables.

If the signal names do not match, the integration model generates additional code to copy data between the signal implemented by the integration model and the signal implemented by the imported code.

hLines = get_param(dstBlock, 'LineHandles');
set(hLines.Inport(1), 'Name', 'ticks', 'StorageClass', 'ExportedGlobal');
set(hLines.Outport(1), 'Name', 'count', 'StorageClass', 'ExportedGlobal');

Configure Storage Class for Parameters and Data Store Memory in Integration Model

The parameters and data stores are implemented through the ImportedExtern storage class in the imported code. If the parameters and data stores are configured to use the ExportedGlobal storage class, the integration model must provide the definitions for the variables.

resetSignal.CoderInfo.StorageClass = 'ExportedGlobal';
countLower.CoderInfo.StorageClass = 'ExportedGlobal';
countUpper.CoderInfo.StorageClass = 'ExportedGlobal';

Generate Code from Integration Model

As the required shared code is now in the shared code repository, remove the previously generated shared utilities folder.

if isdir(RTW.getBuildDir(integrationModel).SharedUtilsTgtDir)
    rmdir(RTW.getBuildDir(integrationModel).SharedUtilsTgtDir, 's');
end

Delete the scope and connecting line that do not affect code generation.

scopeBlock = [integrationModel, '/', 'Scope'];
hScopeLines = get_param(scopeBlock, 'LineHandles');
hScopeLine = hScopeLines.Inport(1);
assert(strcmp(get(hScopeLine, 'SegmentType'), 'branch'));
delete_line(hScopeLine);
delete_block(scopeBlock);

Generate code.

rtwbuild(integrationModel);
### Starting build procedure for model: rtwdemo_crossrelease_integration
### Successful completion of code generation for model: rtwdemo_crossrelease_integration

Examine Call to Imported Code

To examine the cross-release block code within the integration model code, use the rtwtrace utility.

rtwtrace(dstBlock);

Test Code Generated from Integration Model With SIL Simulation

Run a top-model software-in-the-loop (SIL) simulation of the integration model. The simulation runs the code generated from the integration model, which calls the imported code.

Log the simulation output in the workspace.

set_param(integrationModel, 'SimulationMode', 'software-in-the-loop (sil)');
yout_SIL = sim(integrationModel, 'ReturnWorkspaceOutputs', 'on');
plot(yout_SIL.yout{1}.Values);
### Starting build procedure for model: rtwdemo_crossrelease_integration
### Successful completion of build procedure for model: rtwdemo_crossrelease_integration
### 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_crossrelease_integration
### Stopping SIL simulation for component: rtwdemo_crossrelease_integration

Compare Outputs

Compare the outputs from the simulation where only the imported code ran in SIL mode with the outputs from the simulation where the integration model ran as a top-model in SIL mode.

max(abs(yout_SIL.yout{1}.Values.Data - yout_retuned.yout{1}.Values.Data))
ans =

  uint8

   0