Code Generation of WLAN Toolbox Features
This example shows how to generate MEX files and efficient C/C++ code for the WLAN Toolbox™ waveform generator function and verify its correct behavior. Additionally, it shows how to work around limitations of code generation for WLAN Toolbox channel models. All WLAN Toolbox functions and System objects™ are supported for C/C++ code generation.
Introduction
With MATLAB Coder™, you can generate efficient, portable C source code, standalone executables, and MEX functions for deployment in desktop and embedded applications. You can speed up your MATLAB code using MEX functions or integrate generated source code and static or dynamic libraries into your C/C++ code projects. See Setting Up the C or C++ Compiler (MATLAB Coder) for more information about how to set up the C/C++ compiler. In order to use code generation, you need a MATLAB Coder license.
This example uses the codegen
function to generate code for the WLAN Toolbox waveform generator and the TGax channel System object. First, prepare the required input arguments of the waveform generator and configure MATLAB Coder to generate MEX files. Next, compare the output of the generated MEX files and the original MATLAB code. Finally, the example shows how to work around limitations of code generation affecting WLAN Toolbox.
Input Arguments Definition
For code generation, you must specify the size and type of the input arguments to your entry-point function. In this case, you specify the input arguments of the wlanWaveformGenerator
function and packet format configuration object. The mandatory arguments of the waveform generator are the data bits of the physical layer service data unit (PSDU) and the waveform format configuration. Additional inputs such as the idle time, scrambler initialization, and window transition time depend on the format configuration. Specify the additional inputs as name-value pairs. See wlanWaveformGenerator
for more information.
You can use example values of the input arguments and the codegen
function automatically derives their size, class, and complexity. However, the size of the input data vector depends on properties of the format configuration such as the channel bandwidth and coding. Use the coder.typeof
function to define a variable-size input data vector that adapts to the format configuration properties as required.
Thus, you can run the generated code for multiple parameter sets of the format configuration object. For more information about specifying variable-size input arguments, see Generate Code for Variable-Size Data (MATLAB Coder). In this case, specify only the first dimension as variable-size.
variableDims = [1 0];
Variable-size vectors can be upper bounded or unbounded. To allow for full flexibility, you can select the upper bound to be the maximum aggregated MAC protocol data unit (A-MPDU) length, i.e., 6500631 bytes.
upperBound = 6500631*8; % Upper bound in bits
Next, use coder.typeof
to define an input type as a column vector of doubles with a maximum size of upperBound
-by-1, with the first dimension variable-size.
inputBits = coder.typeof(double(0),[upperBound 1],variableDims);
As the inputBits
data type is double, you can only use double-precision values for the input bits of the generated MEX and C/C++ code.
Next, create a high-efficiency single-user (HE SU) format configuration object with default parameters and its corresponding configuration structure using the coder.typeof
function. Use this structure to specify the type and size of any property of the HE SU format configuration object.
cfgHESU = wlanHESUConfig; cfgHESUcg = coder.typeof(cfgHESU);
There are two possible forward-error-correction (FEC) coding types for the HE-Data: low-density parity-check, specified by setting the ChannelCoding
property of cfgHESU
to 'LDPC'
, and binary convolutional coding, specified as 'BCC'
. Since these are character arrays of different lengths, use the coder.typeof
function to define a variable-length row vector of maximum size 1-by-4 characters.
cfgHESUcg.Properties.ChannelCoding = coder.typeof('LDPC',[1 4],[0 1]);
Use the same strategy for the channel bandwidth property. In this case, the longest character array corresponds to 'CBW320'
, so six characters are enough to cover all other possible cases, i.e., 'CBW20'
, 'CBW40'
, 'CBW80'
, 'CBW160'
, and 'CBW320'
.
cfgHESUcg.Properties.ChannelBandwidth = coder.typeof('CBW320',[1 6],[0 1]);
Specify optional arguments of the waveform generator such as the windowing transition time using name-value pairs. Use coder.Constant
to define the name of the argument because it is a string literal that is not expected to change.
WindowTransitionTime_Name = coder.Constant('WindowTransitionTime');
Use an example value from which the codegen
function derives its type and size. This technique is only suitable for fixed-size input arguments.
WindowTransitionTime_Value = 0;
Code Generation for the WLAN Toolbox Waveform Generator
Once the input arguments are specified for code generation, configure MATLAB Coder to generate MEX files and C/C++ code. A MEX file acts as an interface to the generated C/C++ code that can run in MATLAB. MEX file generation is usually the first step in the code generation workflow as it provides a convenient way for verifying the generated C/C++ code.
You can generate a MEX file, C/C++ code, a dynamic library, or a standalone executable by creating a MATLAB Coder configuration object and specifying the build type as 'MEX'
, 'LIB'
, 'DLL'
, or 'EXE'
, respectively.
BuildType = 'MEX';
cfgCoder = coder.config(BuildType);
Generate a report containing useful information about the code generation process.
cfgCoder.GenerateReport = true;
The name of the generated MEX file is the entry-point function name appended by the suffix 'mex', that is, wlanWaveformGenerator_mex
. To specify a different name for your MEX file, use the option -o output_file_name
. You can find the generated MEX files in your local folder and the generated C/C++ code in the folder codegen\mex\wlanWaveformGenerator.
Users of Microsoft Visual C++ product family may see the C4101 compiler warning indicating an unreferenced local variable.
inputArgs = {inputBits,cfgHESUcg,WindowTransitionTime_Name,WindowTransitionTime_Value}; %#ok<NASGU> codegen wlanWaveformGenerator -args inputArgs -config cfgCoder -o wlanWaveformGenerator_HESU_mex
Code generation successful: To view the report, open('codegen/mex/wlanWaveformGenerator/html/report.mldatx')
Next, verify that the generated MEX file behaves as expected when you use different configurations of the ChannelBandwidth
and ChannelCoding
by comparing its output to that of the wlanWaveformGenerator
.
% Create a HE SU format configuration object specifying the channel % bandwidth, coding, number of antennas and streams. cfgHESU = wlanHESUConfig('ChannelBandwidth','CBW20','ChannelCoding','BCC', ... 'NumTransmitAntennas',2,'NumSpaceTimeStreams',2); % Set the value of the window transition time WindowTransitionTime = 1e-09; % Create a PSDU of size defined by the getPSDULength function inputBits = randi([0 1],getPSDULength(cfgHESU)*8,1); % Run the wlanWaveformGenerator waveformMAT = wlanWaveformGenerator(inputBits,cfgHESU,'WindowTransitionTime',WindowTransitionTime); % Run the generated MEX file waveformMEX = wlanWaveformGenerator_HESU_mex(inputBits,cfgHESU,'WindowTransitionTime',WindowTransitionTime); % Compare the outputs of the wlanWaveformGenerator and generated MEX file difference = waveformMAT - waveformMEX; % Check the results are consistent if max(abs(difference),[],'all') > 1e-10 error('The MEX file generated does not produce the same results as wlanWaveformGenerator.') else disp('The outputs of the generated MEX file and the wlanWaveformGenerator are equal.') end
The outputs of the generated MEX file and the wlanWaveformGenerator are equal.
Additional Options for Code Generation
In addition to the reporting options used above, you can configure MATLAB Coder with more advanced options.
Generate C/C++ code only but do not build object code or MEX files setting
cfgCoder.GenCodeOnly = true
. This can save time when you iterate between modifying MATLAB code and inspecting the generated C/C++ code. To generate a MEX file, set this value tofalse
.
Configure MATLAB Coder for optimized C/C++ code generation by setting
cfgCoder.BuildConfiguration = 'Faster Runs'
. This option is available only for'LIB'
,'DLL'
, and'EXE'
build types.
See the coder.config
(MATLAB Coder) reference page for more information.
Limitations of Code Generation
WLAN Channel Models are System objects, which are designed specifically for implementing and simulating dynamic systems with inputs that change over time. Consider these limitations for code generation of System objects:
Nontunable property values must be constant and can only be assigned once before you call the object, including the assignment in the constructor.
You cannot pass in a System object™ to an entry-point function.
See System Objects in MATLAB Code Generation (MATLAB Coder) for more information about rules and limitations of System objects™ for code generation.
If you try to generate code for the entry-point function named hCustomChannelNT
, which creates a wlanTGaxChannel
with a bandwidth specified by the input argument BW
and filters the signal inputSignal
, the code generation process fails.
function signalOut = hCustomChannelNT(BW, signalIn) % Create a TGax channel with the appropriate bandwidth ch = wlanTGaxChannel('ChannelBandwidth',BW); % Filter the input signal signalOut = ch(signalIn); end
The error message indicates: Failed to compute constant value for nontunable property 'ChannelBandwidth'
.
The ChannelBandwidth
property of the wlanTGaxChannel
object is not a constant value because it depends on the input argument BW
of the hCustomChannelNT
function. You can work around this by setting BW
to be a constant value.
inputSignal = coder.typeof(complex(0),[Inf 1],[1 0]); %#ok<NASGU> codegen hCustomChannelNT -args {coder.Constant('CBW320'),inputSignal};
Code generation successful.
However, if you specify a constant value for the channel bandwidth, you cannot change the channel bandwidth at runtime. The following call hCustomChannelNT_mex('CBW20',inputSignal)
fails because the specified argument BW
is not 'CBW320'
. It is possible to work around this for a limited variability of the input arguments using a switch-case block. The function hCustomChannel
contains a switch-case where each of the cases creates a wlanTGaxChannel
with the appropriate channel bandwidth.
function signalOut = hCustomChannel(ChannelBandwidth,signalIn) %hCustomChannel Creates a TGax channel with the appropriate bandwidth, sample rate and filter the input signal switch ChannelBandwidth case 'CBW20' fs = 20e6; % Input signal sample rate ch = wlanTGaxChannel('ChannelBandwidth','CBW20','SampleRate',fs); signalOut = ch(signalIn); case 'CBW40' fs = 40e6; % Input signal sample rate ch = wlanTGaxChannel('ChannelBandwidth','CBW40','SampleRate',fs); signalOut = ch(signalIn); case 'CBW80' fs = 80e6; % Input signal sample rate ch = wlanTGaxChannel('ChannelBandwidth','CBW80','SampleRate',fs); signalOut = ch(signalIn); case 'CBW160' fs = 160e6; % Input signal sample rate ch = wlanTGaxChannel('ChannelBandwidth','CBW160','SampleRate',fs); signalOut = ch(signalIn); case 'CBW320' fs = 320e6; % Input signal sample rate ch = wlanTGaxChannel('ChannelBandwidth','CBW320','SampleRate',fs); signalOut = ch(signalIn); otherwise error('Invalid bandwidth configuration.') end end
Note that hCustomChannel
creates a new channel object every time it is used, so it does not preserve the state of the channel.
Next, generate code for hCustomChannel
and select multiple channel bandwidths at runtime.
inputSignal = coder.typeof(complex(0),[Inf 1],[1 0]); BW = coder.typeof('CBW320',[1 6],[0 1]); inputArgs = {BW,inputSignal}; codegen hCustomChannel -args inputArgs cfgHESU = wlanHESUConfig; cfgHESU.ChannelBandwidth = 'CBW20'; inputSignal = wlanWaveformGenerator_HESU_mex([1 0 1]',cfgHESU,'WindowTransitionTime',0); rng('default') % Set the default random number generator for reproduction purposes outputSignalMEX = hCustomChannel_mex('CBW20',inputSignal); rng('default') outputSignalMAT = hCustomChannel('CBW20',inputSignal); % Calculate the difference between the MEX and MATLAB files outputs difference = outputSignalMAT - outputSignalMEX; % Check the results are consistent if max(abs(difference),[],'all') > 1e-10 error('The generated MEX file does not produce the same results as hCustomChannel.') else disp('The outputs of the generated MEX file and hCustomChannel are equal.') end
Code generation successful. The outputs of the generated MEX file and hCustomChannel are equal.
Change the channel bandwidth and pass the signal through the channel.
cfgHESU.ChannelBandwidth = 'CBW40'; inputSignal = wlanWaveformGenerator_HESU_mex([1 0 1]',cfgHESU,'WindowTransitionTime',0); rng('default') % Set the default random number generator for reproduction purposes outputSignalMEX = hCustomChannel_mex('CBW40',inputSignal); rng('default') outputSignalMAT = hCustomChannel('CBW40',inputSignal); % Calculate the difference between the MEX and MATLAB files outputs difference = outputSignalMAT - outputSignalMEX; % Check the results are consistent if max(abs(difference),[],'all') > 1e-10 error('The MEX file generated does not produce the same results as hCustomChannel.') else disp('The outputs of the generated MEX file and hCustomChannel are equal.') end
The outputs of the generated MEX file and hCustomChannel are equal.
Further Investigation
You can integrate the generated code with the SystemVerilog Direct Programming Interface (DPI) to export MATLAB algorithms to ASIC or FPGA verification environments including Synopsys VCS®, Cadence Incisive or Xcelium, and Mentor Graphics ModelSim or Questa. You can automatically generate SystemVerilog DPI components from MATLAB functions using MATLAB Coder™ with HDL Verifier™. The following workflow can be used with MATLAB functions that generate stimuli and perform analysis or with a MATLAB function that is a behavioral golden reference for the device under test (DUT) in the ASIC or FPGA verification environment. See SystemVerilog DPI Component Generation (HDL Verifier) (HDL Verifier) to learn more.