To improve execution-time profiling of generated code that runs on deterministic hardware, you can run processor-in-the-loop (PIL) simulations that automatically filter the overheads associated with code instrumentation. You can use the target hardware to estimate the average overhead value or you can specify the value manually.
Note
By default, the software filters the execution times of AUTOSAR Runtime Environment (RTE) code and functions that run within Simulink®, for example, Function Caller blocks.
When you create a target connectivity configuration for PIL simulations, through an
rtw.connectivity.Config
subclass, you can specify functions that estimate and
remove instrumentation overheads from execution-time measurements. At the start of a
processor-in-the-loop (PIL) simulation, the software runs a benchmark program a specified
number of times and obtains an average value for the instrumentation overheads. The
benchmark program estimates the overheads for the timer API and for timer freezing and
unfreezing, task, and function instrumentation code.
During the simulation, the software subtracts the average value of instrumentation overheads from the execution-time measurements. The Simulation Data Inspector and the code execution profiling report display the corrected measurement values.
This figure shows how the uncorrected and corrected timer values correspond to invocations of code sections.
The corrected timer value excludes execution time associated with instrumentation code, RTE code, and function code that runs within Simulink.
To estimate and remove instrumentation overheads from execution-time measurements, the
rtw.connectivity.Config
class provides these functions.
Function | Description |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
When you set up target connectivity for processor-in-the-loop (PIL) simulations,
configure the removal of the instrumentation overheads through an rtw.connectivity.Config
subclass. For example, this code shows how you can run
the benchmark
program.
classdef overheadConnectivityConfig < rtw.connectivity.Config methods function this = customConnectivityConfig(componentArgs) % Create builder targetApplicationFramework = ... mypil.TargetApplicationFramework(componentArgs); builder = rtw.connectivity.MakefileBuilder(componentArgs, ... targetApplicationFramework, ''); % Create launcher launcher = mypil.Launcher(componentArgs, builder); % Set up communication hostCommunicator = rtw.connectivity.RtIOStreamHostCommunicator(... componentArgs, ... launcher, ... rtiostreamLibTCPIP); % Call super class constructor to register components this@rtw.connectivity.Config(componentArgs,... builder,... launcher,... hostCommunicator); % Register hardware-specific timer, which enables % code execution profiling. This example uses a % timer for the host platform. timer = coder.profile.crlHostTimer(); this.setTimer(timer); % Specify removal of profiling instrumentation overheads this.activateOverheadFiltering(true); this.runOverheadBenchmark(true); this.setOverheadBenchmarkSteps(50); end end end
Instead of running the benchmark program, you can use setOverheads
to
provide your values for instrumentation
overheads.
... % Remove instrumentation overhead using manually specified values this.activateOverheadFiltering(true); this.setOverheads (taskInstrumentationOverhead, ... functionInstrumentationOverhead, freezingInstrumentation); ...
When a PIL simulation is complete, you can retrieve benchmark results from the variable
that you specify in the Code Generation > Verification > Workspace variable field (CodeExecutionProfileVariable
), for example,
myExecutionProfile
.
benchmarkResults = myExecutionProfile.getOverheadBenchmarkData();
benchmarkResults
is a structure that contains code
instrumentation overhead
values.
>> benchmarkResults ans = struct with fields: TimestampOverhead: [1×1 struct] TaskOverhead: [1×1 struct] FunctionOverhead: [1×1 struct] FreezingOverhead: [1×1 struct] >> benchmarkResults.TaskOverhead ans = struct with fields: Data: [1×100 uint64] NumSamples: 100 Average: 45.2800