C Code Optimization Using MATLAB Coder app for Hexagon DSP
This example demonstrates the workflow of generating optimized C code from MATLAB® Coder app for the Qualcomm Hexagon Simulator using the Embedded Coder® Support Package for Qualcomm® Hexagon® Processors and the Qualcomm Hexagon QHL Code Replacement Library (CRL). The example utilizes a dsp.FIRFilter System object to filter two sine waves with different frequencies.
Supported Hardware
Qualcomm Hexagon Simulator
Qualcomm Hexagon Android Board
Prerequisites
Launch the hardware setup and install the Qualcomm SDK. For more information, see Launch Hardware Setup.
Required Hardware
To run this example, you need the following hardware:
Supported Qualcomm Hexagon Simulator
Generate Code using MATLAB Coder app
Open MATLAB Coder App and Select Source Files
On the MATLAB toolstrip Apps tab, under Code Generation, click the MATLAB Coder app icon. The app opens the Select Source Files page.
In the Select Source Files page, enter or select the name of the entry-point function ex_fir_hexagon_ml. An entry-point function is a top-level MATLAB function from which you generate code. The app creates a project with the default name ex_fir_hexagon_ml.prj in the current folder.
3. Click Next to go to the Define Input Types step.
Define Input Types
The code generator determines the class, size, and complexity of all variables in the MATLAB files at code generation time, also known as compile time. Therefore, you must specify the properties of all entry-point function inputs. To specify input properties, you can:
Specify properties directly (manually).
Instruct the app to automatically determine input properties by providing a script (in this example, ex_fir_hexagon_test) that calls the entry-point functions with sample inputs.
Enter or select the test file ex_fir_hexagon_test.m.
Click Autodefine Input Types.
3. Click Next to go to the Check for Run-Time Issues step.
Check for Run-Time Issues
The Check for Run-Time Issues step generates a MEX file from your entry-point functions, runs the MEX function, and reports any issues. A MEX function is generated code that can be called from within MATLAB. It is recommended to perform this step because it allows you to detect and fix run-time errors in the generated C code. By default, the MEX function includes memory integrity checks, which perform array bounds and dimension checking to detect violations of memory integrity in the code generated for MATLAB functions.
Upon clicking Next, the coder will check for any general runtime issues in the plain C code. This step is optional and can be skipped if the CRL is being used.
To open the Check for Run-Time Issues dialog box, click the Check for Issues arrow .
In the Check for Run-Time Issues dialog box, specify a test file or enter code that calls the entrypoint function with example inputs. For this example, use the test file test that you used to define the input types.
Click Check for Issues.
By default, the app collects line execution counts. These counts help you to see how well the test file ex_fir_hexagon_test.m exercised the function. To view line execution counts, click View MATLAB line execution counts. The app editor displays a color-coded bar to the left of the code. To extend the color highlighting over the code and to see line execution counts, place your cursor over the bar.
Generate C Code
In the Generate Code tab, configure this code generation settings:
Set Hardware Board to Qualcomm Hexagon Simulator.
Clear the Generate Code Only option.
Set More Settings > Custom Code > Code replacement library to Qualcomm Hexagon QHL.
Check More Settings > Debugging > Always create a report.
Check More Settings > Debugging > Code replacements.
Set hardware configuration settings from More Settings > Hardware > Device > Processor Version to 'V68'. Similarly, Clocking > DSP Clock (MHz) to 300.
After updating the code generation settings, click on Generate to initiate the code generation process.
Upon successful code generation, you will be able to view the generated code and the generated report.
Numerical Verification of Generated Code
To manually verify numerical accuracy, follow a workflow similar to the codegen command line. Click Run manually in MATLAB under VERIFY CODE to initiate the verification process. This action generates the <codegen function>_pil.mex
file, which shares the same interface as ex_fir_hexagon_ml.m
. You can then compare the outputs of these functions when provided with the same inputs.
After the above step, you can run the below code:
% numSamples = 120; % sin1 = dsp.SineWave('Amplitude',1,'Frequency',1000,... % 'SampleRate',16000, 'SamplesPerFrame', numSamples,... % 'OutputDataType', 'single'); % sin2 = dsp.SineWave('Amplitude',4,'Frequency',5000,... % 'SampleRate',16000, 'SamplesPerFrame', numSamples,... % 'OutputDataType', 'single'); % % numSteps = 200; % frameLength = sin1.SamplesPerFrame; % yRef = zeros(frameLength,1,numSteps,'single'); % y = zeros(frameLength,1,numSteps,'single'); % % for k = 1:numSteps % x1k = sin1(); % generate 1KHz sine wave % x5k = sin2(); % generate 5KHz sine wave % n = randn(size(x1k), 'single')*sqrt(.05); % generate noise signal % u = x1k+x5k+n; % % Run with MATLAB code on host machine % yRef(:,:,k) = ex_fir_hexagon_ml(u); % % Run with generated code on target % y(:,:,k) = ex_fir_hexagon_ml_pil(u); % end % clear ex_fir_hexagon_ml; % clear ex_fir_hexagon_ml_pil;
After the execution, you can compare the outputs of the PIL against the reference using any norm function.
% % norm comparison of y & yRef % absoluteError = norm(y(:)-yRef(:),'inf'); % fprintf("Absolute error = %g \n",absoluteError);
Alternatively, you can use the verifyEqual
function from the matlab.unittest.TestCase.forInteractiveUse
test class. This function allows you to compare the outputs against the given absolute and relative tolerances, concluding the overall results.
% reltol = single(1e-5); % abstol = single(1e-5); % matlab.unittest.TestCase.forInteractiveUse.verifyEqual(y,yRef, ... % 'RelTol',reltol, 'AbsTol', abstol);
Analyze Performance using Code Profile Analyzer
The MATLAB Coder App provides users with the ability to profile the generated code and offers various utilities for performance analysis. To perform profiling, follow this steps:
Go to the VERIFY CODE option.
Select the script which calls the target function.
Enable the options Enable entry point execution profiling and Enable function execution profiling.
Set the Run using option to Generate Code.
Click on Run Generated Code to initiate the profiling process.
This enables the coder to generate <codegen function>_pil.mex file, which runs in MATLAB and interacts with the target to deploy and execute target-specific code. It's important to note that the verification process may take time, depending on the complexity of the test script.
Once the testing is completed, a green pop-up will appear at the bottom of the app, indicating the completion of the verification process.
After the verification process is complete, you can click on Stop PIL Verification. This action will enable a link in the Test Output window, allowing you to view the profiling information. By clicking on the link, you can access and analyze the profiling results for further performance evaluation.
Click the profiling report link to generate the report.
This will display various metrics of the profiled time, such as average execution time, etc.
Considering the maximum execution time of the ex_fir_hexagon_ml
function, which is 17,072 cycles, repeating the code profiling with the Code Replacement Library set to None resulted in the same function taking 42,188 cycles. This indicates that enabling the CRL improved the cycle performance of ex_fir_hexagon_ml
by approximately 50%.
Code Generation Summary
The summary of the coder app will have all the links to report, generated code locations and dependencies.
Note: For Qualcomm Hexagon QHL CRL, explicit alignment specification for buffers is necessary only when the input/output variables are directly used in the operators, functions and system-objects.