Interactively Trace Between MATLAB Code and Generated C/C++ Code - MATLAB & Simulink (original) (raw)
This example shows how to trace between MATLAB® source code and the generated C/C++ code. Tracing between source code and generated code helps you to:
- Understand how the code generator implemented your algorithm.
- Debug issues in the generated code.
- Evaluate the quality of the generated code.
If you have Embedded Coder® and enable production of a code generation report with traceability, you can view MATLAB source code and generated C/C++ code next to each other. As you move your pointer over code, you can follow highlighted traces to the corresponding generated code or source MATLAB code.
Create the MATLAB Source Code
To illustrate interactive traceability, this example produces a report for generation of a C static library for a MATLAB function lpsolve
that solves the linear program:
- maximize y = c*x
- subject to A*x <= b
- where x >= 0 and b >= 0
%Attempts to solve the linear program:
%
% maximize y = cx
% subject to: Ax <= b,
% where x >= 0 and b >= 0
%
% using the dictionary form of the simplex algorithm.
%
% c must be a double, real row vector.
% b must be a double, real column vector.
% A must be a double, real, non-empty matrix with
% size(A) = [length(b),length(c)].
%
% Compare to
% x = linprog(-c(:),A,b,[],[],zeros(length(c),1))
% y = c*x
%
% Copyright 2011-2018 The MathWorks, Inc.
function [x,y] = lpsolve(c,A,b) %#codegen narginchk(3,3); m = int32(size(A,1)); n = int32(size(A,2)); if ~validInputs(c,A,b) % Something is wrong with the inputs. Return NaNs. x = nan(n,1); y = nan; return end cn = c; nIdx = 1:n; % indices of non-basic variables bIdx = n + (1:m); % indices of basic variables % Perform iterations. j = findPivotColumn(cn,nIdx); unbounded = false; while j > 0 && ~unbounded [i,r] = findPivotRow(j,A,b); if i == 0 || isinf(r) unbounded = true; else b(i) = r; % Take account of the variables entering and leaving the basis. entering = nIdx(j); leaving = bIdx(i); bIdx(i) = entering; nIdx(j) = leaving; [cn,A,b] = pivot(cn,A,b,i,j); j = findPivotColumn(cn,nIdx); end end % Construct the solution. if unbounded x = nan(n,1); y = inf; else x = zeros(n,1); y = 0; for k = 1:m j = bIdx(k); if j <= n x(j) = b(k); y = y + c(j)*x(j); end end end
%-------------------------------------------------------------------------------
function p = validInputs(c,A,b) coder.inline('never'); % All inputs must be double. p = isa(c,'double') && isa(A,'double') && isa(b,'double'); % All inputs must be real. p = p && isreal(c) && isreal(A) && isreal(b); % A must be a non-empty matrix. p = p && ismatrix(A) && ~isempty(A); % c must be a row-vector with length = size(A,2). p = p && isrow(c) && size(c,2) == size(A,2); % b must be a column-vector with length = size(A,1). p = p && iscolumn(b) && size(b,1) == size(A,1); % The elements of b must be non-negative. p = p && all(b(:) >= 0);
%-------------------------------------------------------------------------------
function [c,A,b] = pivot(c,A,b,i,j) % Pivot on element i,j. coder.inline('never'); m = int32(size(A,1)); aij = A(i,j); A(i,j) = 1; A(i,:) = A(i,:)/aij; for k = 1:m if k ~= i akj = A(k,j); A(k,j) = 0; A(k,:) = A(k,:) - akjA(i,:); b(k) = b(k) - akjb(i); end end cj = c(j); c(j) = 0; c = c - cj*A(i,:);
%-------------------------------------------------------------------------------
function j = findPivotColumn(c,idx) % Find a suitable variable to enter the basis using the smallest % subscript rule to prevent cycling. coder.inline('never'); j = int32(0); nc = int32(numel(c)); lastidx = int32(0); for k = 1:nc if c(k) > 0 && (lastidx < 1 || idx(k) < lastidx) j = k; lastidx = idx(k); end end
%-------------------------------------------------------------------------------
function [i,r] = findPivotRow(j,A,b) % Find the pivot row in column j of A and also return r = b(i)/A(i,j). coder.inline('never'); r = inf; i = int32(0); nb = int32(numel(b)); for k = 1:nb if A(k,j) > 0 rtmp = b(k)/A(k,j); if rtmp < r r = rtmp; i = k; end end end
%-------------------------------------------------------------------------------
The example also uses a test function lpsolve_test
that callslpsolve
with representative input values.
% Test function for lpsolve % % Copyright 2011-2018 The MathWorks, Inc.
function lpsolve_test() c = [2 3 1 1]; A = [2 3 1 -1;1 0 2 1;0 2 1 1]; b = [27;9;18]; [x,y] = lpsolve(c,A,b); x % display x y % display y
In a writable folder, create the files lpsolve.m
andlpsolve_test.m
by copying the code from the expanders in this section.
Prepare for Code Generation
Before you generate C/C++ code, it is a best practice to screen your MATLAB code for code generation readiness.
coder.screener('lpsolve')
The code generation readiness report indicates that lpsolve
is suitable for code generation.
It is also a best practice to check for run-time issues by generating and testing a MEX function.
- To specify the types of the inputs arguments, pass representative input values to the
codegen
-args
option. Alternatively, because you have a test function, you can use coder.getArgTypes to determine the types. - To generate and test a MEX function, use the
-test
option.
c = [2 3 1 1]; A = [2 3 1 -1;1 0 2 1;0 2 1 1]; b = [27;9;18]; codegen lpsolve -args {c A b} -test lpsolve_test
Running test file: 'lpsolve_test' with MEX function 'lpsolve_mex'.
x =
5
7
0
4
y =
35
codegen
successfully generates and runs the MEX function.
Produce a Code Generation Report with Traceability
To generate a report that has interactive traceability:
- Create a
coder.EmbeddedCodeConfig
object. TheEnableTraceability
property controls traceability. By default, theEnableTraceability
property istrue
. - Specify the types of the input arguments by passing representative input values to the
-args
option. - Enable production of a code generation report by using the
-report
option.
cfg = coder.config('lib', 'ecoder', true); codegen -config cfg lpsolve -args {c A b} -report
Access Trace Mode in the Report
To open the code generation report, click View report.
In the code pane, you see lpsolve.m
.
To enable tracing, on the Report tab, click Trace Code.
You see the MATLAB source code and the generated C code next to each other.
Trace Code
You can trace from the MATLAB code to the C code or from the C code to the MATLAB code. Traceable code is marked with blue on the side that you are tracing from and with orange on the side that you are tracing to. As you move your pointer over traceable code, the code is highlighted in purple and you see the traces to the corresponding code on the other side. When you select highlighted code by clicking it, the code becomes yellow and you can see the traces even when you move your pointer away from the selection. The code remains selected until you press Esc or select different code. To change the side that you are tracing from, select code on the other side.
Explore tracing in the example report.
- In the MATLAB code, point to the
while
-loop that starts at line 38 and scroll down until the entirewhile
-loop is in view.
You see this symbol that tells you that the highlighted MATLAB code has one trace that is not in view.
You see the corresponding C code in a separate window in the C code pane. - In the C code pane, scroll down until you see the C code that corresponds to the
while
loop. - In the MATLAB code, move your pointer over different syntax elements in the
while
loop. Highlight variables, expressions, and code blocks.
When you move your pointer over expressions that are part of larger expressions, different shades of purple help you to find the relevant expression in the corresponding C code. For example, at line 43, pause overi
. - In the MATLAB code, move your pointer back to the
while
-loop that starts at line 38. When the entire loop is highlighted in purple, select it by clicking. When you move your pointer outside of the trace, the yellow highlighting identifies the selected trace.
To clear the selection, press Esc or select different code.
View Multiple Traces
When code traces to more than one place in the corresponding source or generated code:
- If you pause over the code that you are tracing, at the top of the code pane, you see the number of traces.
- If some traces are not in view, you see a symbol that tells you how many traces are out of view.
- In the code pane, if you select the code that you want to trace, at the top of the code pane, you can select the trace that you want to see.
In the report for lpsolve
, view multiple traces.
- Pause over line
36
.
At the top of the code pane, you see that line36
has two traces. - Select line
36
.
At the top of the code pane, you see the location of the first trace. - To list all traces, click the arrow to the right of the traces.
View Traces to Different Files
In the code generation report for lpsolve
, all traces from the MATLAB code go to one C file lpsolve.c
. If MATLAB code traces to multiple C files, above the C code, you see a symbol such as that provides the number of additional files in which you can find a trace. If you click the symbol, you can select the file that you want to see. If you select the MATLAB code, then you can select the trace that you want to see.
Likewise, above the MATLAB source code, a symbol such as indicates that the highlighted C code traces to multiple MATLAB files.
Switch the Locations of the Source and Generated Code
- To view
lpsolve.c
on the left side of the code pane, in the list of generated files, clicklpsolve.c
. - To view the MATLAB code on the left side of the code pane, click a MATLAB function, for example,
lpsolve
.
Enable Code Tooltips and Links
When you are not in trace mode:
- In the MATLAB code, if you point to a variable or expression, a tooltip provides information such as the type.
- In the C code, links go to other parts of the code such as type or function definitions.
When you are in trace mode, to enable MATLAB code tooltips and C code links, hold down Ctrl. MATLAB code tooltips are available only for a selected MATLAB function.
In the report for lpsolve
, view type information for a variable.
- In the MATLAB Source pane, select
pivot
. - In the code pane, hold down Ctrl and pause over the input argument
i
.
Note
On a Macintosh platform, use the Command key instead ofCtrl.
Disable Traceability
To produce a code generation report that does not include traceability:
- In a
coder.EmbeddedCodeConfig
object, set theEnableTraceability
property tofalse
. - In the MATLAB Coder™ app, set Enable code traceability to
No
.