Integrate Generated Code by 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 Cross-Release Code Integration.
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.
This example uses generated code from the current release.
model = 'CrossReleaseCounter'; close_system(model,0) load_system(model) set_param(model, 'SimulationCommand', 'update'); open_system(model) slbuild(model);
### Starting build procedure for: CrossReleaseCounter ### Successful completion of code generation for: CrossReleaseCounter Build Summary Top model targets: Model Build Reason Status Build Duration ========================================================================================================= CrossReleaseCounter Information cache folder or artifacts were missing. Code generated. 0h 0m 11.333s 1 of 1 models built (0 models already up to date) Build duration: 0h 0m 12.662s
Identify the build folder that contains the generated code.
buildFolder = RTW.getBuildDir(model).BuildDirectory;
Identify the folder that contains code for shared utilities associated with the generated code.
previousSharedCodeFolder = RTW.getBuildDir(model).SharedUtilsTgtDir;
To reuse generated code from a previous release:
On the Simulation tab, in the File section, select Save > Previous Version.
In the Save as type field, specify the release and model type.
Click Save.
Use the previous release to open the saved model, and then generate code.
Set the value of
buildFolder
to the location of the code generated in the previous release.Set the value of
previousSharedCodeFolder
to the location of the shared utilities generated in the previous release.
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); sharedCodeUpdate(previousSharedCodeFolder, sharedCodeRepo, 'Interactive', false);
The following files will be copied from slprj/ert/_sharedutils to SharedCodeRepo/R2024b: rtwtypes.h Files copied from slprj/ert/_sharedutils to SharedCodeRepo/R2024b.
Import Code
Load the integration model.
integrationModel = 'CrossReleaseIntegration';
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(buildFolder, cs, 'SimulationMode', 'SIL');
### Starting import process for component: CrossReleaseCounter_R2024b ### Starting build process for SIL block: CrossReleaseCounter_R2024b
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/CrossReleaseCounter_R2024b_sil CrossReleaseIntegration/Counter
Simulate Integration Model
Run a simulation of the integration model.
sim(integrationModel)
### Preparing to start SIL block simulation: <a href="matlab: targets_hyperlink_manager('run',1);">CrossReleaseIntegration/Counter</a> ... ### Starting SIL simulation for component: CrossReleaseCounter_R2024b_sil ### Application stopped ### Stopping SIL simulation for component: CrossReleaseCounter_R2024b_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. Use these parameters to modify the behavior of the SIL simulation.
countUpper.Value = 30; countLower.Value = 20; yout_retuned = sim(integrationModel, 'ReturnWorkspaceOutputs', 'on');
### Preparing to start SIL block simulation: <a href="matlab: targets_hyperlink_manager('run',1);">CrossReleaseIntegration/Counter</a> ... ### Starting SIL simulation for component: CrossReleaseCounter_R2024b_sil ### Application stopped ### Stopping SIL simulation for component: CrossReleaseCounter_R2024b_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'); % Use the code mappings API to configure the storage class on the signals. cm = coder.mapping.api.get(integrationModel); ticksPortHandle = get(hLines.Inport(1), 'SrcPortHandle'); set(ticksPortHandle, 'Name', 'ticks'); addSignal(cm, ticksPortHandle); setSignal(cm, ticksPortHandle, 'StorageClass', 'ExportedGlobal'); countPortHandle = get(hLines.Outport(1), 'SrcPortHandle'); set(countPortHandle, 'Name', 'count'); addSignal(cm, countPortHandle); setSignal(cm, countPortHandle, '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 you configure the parameters and data stores 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
Once the required shared code is in the shared code repository, remove the previously generated shared utilities folder.
if isfolder(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.
slbuild(integrationModel);
### Starting build procedure for: CrossReleaseIntegration ### Successful completion of code generation for: CrossReleaseIntegration Build Summary Top model targets: Model Build Reason Status Build Duration ============================================================================================================= CrossReleaseIntegration Information cache folder or artifacts were missing. Code generated. 0h 0m 13.309s 1 of 1 models built (0 models already up to date) Build duration: 0h 0m 14.348s
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
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: CrossReleaseIntegration ### Successful completion of build procedure for: CrossReleaseIntegration Build Summary Top model targets: Model Build Reason Status Build Duration =============================================================================================================================== CrossReleaseIntegration S-function CrossReleaseCounter_R2024b_sil did not exist. Code generated and compiled. 0h 0m 11.471s 1 of 1 models built (0 models already up to date) Build duration: 0h 0m 12.367s ### Preparing to start SIL simulation ... Building with 'gcc'. MEX completed successfully. ### Updating code generation report with SIL files ... ### Starting SIL simulation for component: CrossReleaseIntegration ### Application stopped ### Stopping SIL simulation for component: CrossReleaseIntegration
Compare Simulation 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