Generate C/C++ Code and Test for Equivalence - MATLAB & Simulink (original) (raw)
You can write equivalence tests that use MATLAB® Coder™ to generate C/C++ code from MATLAB source code, execute the generated code with specified inputs, and verify that the execution of the generated code and the MATLAB source code match.
Equivalence tests can:
- Use MATLAB testing framework customizations, such as parameterizations.
- Qualify test results with absolute and relative tolerances.
- Generate C/C++ code with code generation parameters specified in coder.MexCodeConfig (MATLAB Coder) or coder.EmbeddedCodeConfig (MATLAB Coder) objects.
- Execute and verify C/C++ code that you previously generated outside of the test by using codegen (MATLAB Coder).
- Execute and verify your generated production C/C++ code in software-in-the-loop (SIL) or processor-in-the-loop (PIL) mode. For more information, see Code Verification Through Software-in-the-Loop and Processor-in-the-Loop Execution (Embedded Coder).
You can also generate C/C++ code from multiple entry-point functions or with multiple signatures and then test each function or signature for equivalence with MATLAB source code. For more information, see Equivalence Test C/C++ Code for Multiple Entry-Point Functions and Function Signatures.
Note
You must have MATLAB Coder to run equivalence tests for generated C/C++ code for MEX targets and Embedded Coder® for LIB and DLL targets.
If you need to deploy C++ shared libraries, you can write equivalence tests that use MATLAB Compiler SDK™ to generate and test deployable C++ shared libraries from MATLAB source code. For more information, see Choose an Approach for Equivalence Testing Generated C++ Code.
Write Generated C/C++ Code Equivalence Tests
To write an equivalence test that generates and tests C/C++ code, define a test class that inherits from matlabtest.coder.TestCase. In your test class, include amethods
block with the Test
attribute. In themethods
block, add a function to contain the test.
classdef tEquivalence < matlabtest.coder.TestCase methods (Test) function equivalenceTest(testCase)
end
end
end
For more information about test classes, see Class-Based Unit Tests.
Equivalence tests typically do three things:
- Build — Generate the C/C++ code by using the build function.
- Execute — Execute the C/C++ code by using the execute function.
- Qualify — Qualify the result by comparing the execution of the C/C++ code to the execution of the MATLAB source code by using methods such as verifyExecutionMatchesMATLAB. For more information, see Table of Qualifications for Equivalence Tests.
Suppose that you want to generate code for a function calledmyAdd
, which adds two inputs and outputs the result:
function y = myAdd(a,b) %#codegen y = a + b; end
This equivalence test builds C code for a MEX target with inputs set to(1,2)
. It executes the C code with the same inputs used to build the code and verifies that the execution matches the MATLAB execution of the function.
classdef tEquivalence < matlabtest.coder.TestCase methods(Test) function tMyAdd(testCase) buildResults = build(testCase,"myAdd",Inputs={1,2}); executionResults = execute(testCase,buildResults); verifyExecutionMatchesMATLAB(testCase,executionResults) end end end
Tip
You can generate code that accepts variable-sized inputs by using the output of coder.typeof (MATLAB Coder) as a build-time input. However, if you specify build-time inputs usingcoder.typeof
, you must specify real run-time inputs for the execute method.
By default, the test case generates code in a temporary directory. To preserve the generated files, use the PreserveInFolder name-value argument in the build method. When the equivalence test fails, MATLAB preserves the generated files regardless of whether or not you use this name-value argument.
Parameterize Equivalence Tests
Equivalence tests use the MATLAB test framework, which means you can use MATLAB test customizations such as parameterizations. Parameterized tests allow you to test different parameter combinations with less code than if you coded each combination separately. For more information, see Create Basic Parameterized Test. Parameterizing equivalence tests allows you to generate the C/C++ code once and test it with different parameter combinations.
This example equivalence test generates the C code once by using class-level properties and test setup methods, but executes the code multiple times with different inputs by using parameterization.
classdef tEquivalenceParameterized < matlabtest.coder.TestCase properties buildResults end
methods (TestClassSetup)
function generateCode(testCase)
testCase.buildResults = build(testCase,"myAdd", ...
Inputs={1,2});
end
end
properties (TestParameter)
runTimeInputs = {{1,2},{3,5}};
end
methods (Test)
function tMyAdd(testCase,runTimeInputs)
executionResults = execute(testCase, ...
testCase.buildResults,Inputs=runTimeInputs);
verifyExecutionMatchesMATLAB(testCase,executionResults)
end
end
end
This test runs twice. The first time, it executesmyAdd
with inputs set to (1,2)
and the second time it executes with inputs set to (3,5)
.
Generate C/C++ Code with Additional Options
To customize how MATLAB Coder builds your C/C++ code in the equivalence test, create an instance of a code generation configuration parameter object for your desired build type by usingcoder.config (MATLAB Coder) and pass the object to thebuild
method by using the Configuration name-value argument.
This example equivalence test generates a dynamically linked library of C++ code with dynamic memory allocation disabled. The test then executes the C++ code and verifies that the generated code is functionally equivalent to the MATLAB code.
classdef tEquivalenceBuildOptions < matlabtest.coder.TestCase methods (Test) function tMyAdd(testCase) cfg = coder.config("dll",ecoder=true); cfg.TargetLang = "C++"; cfg.EnableDynamicMemoryAllocation = false;
buildResults = build(testCase,"myAdd",Inputs={1,2}, ...
Configuration=cfg);
executionResults = execute(testCase,buildResults);
verifyExecutionMatchesMATLAB(testCase,executionResults)
end
end
end
Alternatively, you can use the CodeGenerationArguments name-value argument in the build method with values from the options (MATLAB Coder) input argument for the codegen (MATLAB Coder) function. For example, you can generate a static C library for a function called myAdd
by using this code:
buildResults = build(testCase,"myAdd", ... Inputs={1,2},CodeGenerationArguments={"-config:lib"});
Specify Target Language as C++
By default, equivalence tests generate C code. To specify the target language as C++, set the value of the CodeGenerationArguments argument of the build method to {"-lang:c++"}
. For example:
buildResults = build(testCase,functionToBuild, ... CodeGenerationArguments={"-lang:c++"});
Use this approach if the target language is the only code generation option that you need to specify, or if you do not need to re-use the code generation options.
Alternatively, you can use the coder.config (MATLAB Coder) function to create a code generation configuration object, specify the TargetLang
property of the object as"C++"
, then pass the object to the build method by using the Configuration argument. For example:
cfg = coder.config("mex"); cfg.TargetLang = "C++"; buildResults = build(testCase,functionToBuild, ... Configuration=cfg);
Use this approach if you need to set many code generation options, or if you need to re-use the code generation options.
Test Existing Generated C/C++ Code
You can generate C/C++ code outside of a test and verify the code by using an equivalence test. To test existing generated C/C++ code for equivalence, use codegen (MATLAB Coder) to generate C/C++ code and pass the file path for the MEX function to the execute method.
This example code shows how to generate code for the myAdd
function outside of a test:
codegen myAdd -args {1,2}
This example equivalence test executes and verifies the existing generated C/C++ code:
classdef tEquivalenceExistingCode < matlabtest.coder.TestCase methods (Test) function tMyAdd(testCase) mexPath = "C:\Users\jdoe\generatedCodeTests\codegen" + ... "\mex\myAdd\myAdd_mex.mexw64"; executionResults = execute(testCase,mexPath,Inputs={5,5}); verifyExecutionMatchesMATLAB(testCase,executionResults) end end end
Execute and Verify in SIL or PIL Mode
With Embedded Coder, you can verify generated C/C++ code with software-in-the-loop (SIL) and processor-in-the-loop (PIL) execution. For more information about SIL and PIL execution, see Code Verification Through Software-in-the-Loop and Processor-in-the-Loop Execution (Embedded Coder).
SIL Verification
To verify generated C/C++ code in SIL mode, generate code for a LIB or DLL target. By default, the equivalence test verifies LIB and DLL targets in SIL mode even if the verification mode is set to none.
This example equivalence test generates a static C library from the functionmyAdd
and executes and verifies the function in SIL mode.
classdef tEquivalenceSIL < matlabtest.coder.TestCase methods (Test) function tMyAddSIL(testCase) buildResults = build(testCase,"myAdd",Inputs={1,2}, ... Configuration="lib"); executionResults = execute(testCase,buildResults); verifyExecutionMatchesMATLAB(testCase,executionResults) end end end
PIL Verification
To verify generated C/C++ code with PIL verification, in your equivalence test method:
- Use coder.config (MATLAB Coder) to create an Embedded Coder configuration parameter object.
- Set the
VerificationMode
property toPIL
. - Configure the Hardware (MATLAB Coder) property of your configuration parameter object for your processor hardware by using coder.hardware (MATLAB Coder).
This example equivalence test generates a static C library from the function myAdd
for an ARM® Cortex®-M3 board. It then executes and verifies the generated code in PIL mode.
classdef tEquivalencePIL < matlabtest.coder.TestCase methods(Test) function tMyAddPIL(testCase) cfg = coder.config("lib","ecoder",true); cfg.VerificationMode = "PIL"; cfg.Hardware = coder.hardware("ARM Cortex-M3 (QEMU)");
buildOut = build(testCase,"myAdd.m",Inputs={1,2}, ...
Configuration=cfg);
executionOut = execute(testCase,buildOut);
verifyExecutionMatchesMATLAB(testCase,executionOut);
end
end
end
Run Tests and View Results
You can run equivalence tests by using the:
- runtests function at the MATLAB command line
- Run Tests button in the MATLAB Editor toolstrip in the Editor tab
- Run button
in the Test Browser
- Run button
in the MATLAB Test Manager
- Run button
in the Code Quality Dashboard
For more information, see Run MATLAB Tests.
See Also
Classes
- matlabtest.coder.TestCase | matlabtest.coder.results.BuildResults | matlabtest.coder.results.ExecutionResults
Functions
Topics
- Generate C Code and Test for Equivalence
- Equivalence Test C/C++ Code for Multiple Entry-Point Functions and Function Signatures
- Collect Coverage for Generated C/C++ Code in Equivalence Tests
- Class-Based Unit Tests
- Generate Deployed Code Artifacts and Test for Equivalence
- Generate C Code at the Command Line (MATLAB Coder)