Code Generation

Code Generation Use and Benefits

You can use the Phased Array System Toolbox™ software together with the MATLAB® Coder™ product to create C/C++ code that implements your MATLAB functions and models. With this software, you can

  • Create a MEX file to speed up your own MATLAB application.

  • Generate a stand-alone executable that runs independently of MATLAB on your own computer or another platform.

  • Include System objects in the same way as any other element.

In general, the code you generate using the toolbox is portable ANSI® C code. In order to use code generation, you need a MATLAB Coder license. Using Phased Array System Toolbox software requires licenses for both the DSP System Toolbox™ and the Signal Processing Toolbox™. See the Getting Started with MATLAB Coder (MATLAB Coder) page for more information.

Creating a MATLAB Coder MEX-file can lead to substantial acceleration of your MATLAB algorithms. It is also a convenient first step in a workflow that ultimately leads to completely standalone code. When you create a MEX-file, it runs in the MATLAB environment. Its inputs and outputs are available for inspection just like any other MATLAB variable. You can use MATLAB’s visualization, and other tools, for verification and analysis.

Within your code, you can run specific commands either as generated C code or by running using the MATLAB engine. In cases where an isolated command does not yet have code generation support, you can use the coder.extrinsic command to embed the command in your code. This means that the generated code reenters the MATLAB environment when it needs to run that particular command. This also useful if you wish to embed certain commands that cannot generate code (such as plotting functions).

The simplest way to generate MEX-files from your MATLAB code is by using the codegen function at the command line. Often, generating a MEX-files involves nothing more than invoking the coder command on one of your existing functions. For example, if you have an existing function, myfunction.m, you can type the commands at the command line to compile and run the MEX function. codegen adds a platform-specific extension to this name. In this case, the "mex" suffix is added.

codegen myfunction.m
myfunction_mex;

You can generate standalone executables that run independently of the MATLAB environment. You can do this by creating a MATLAB Coder project inside the MATLAB Coder Integrated Development Environment (IDE). Alternatively, you can issue the codegen command in the command line environment with appropriate configuration parameters. To create a standalone executable, you must write your own main.c or main.cpp function. See Generating Standalone C/C++ Executables from MATLAB Code (MATLAB Coder) for more information.

Set Up Your Compiler

Before using codegen to compile your code, you must set up your C/C++ compiler. For 32-bit Windows platforms, MathWorks® supplies a default compiler with MATLAB. If your installation does not include a default compiler, you can supply your own compiler. For the current list of supported compilers, see Supported and Compatible Compilers on the MathWorks Web site. Install a compiler that is suitable for your platform. Then, read Setting Up the C or C++ Compiler (MATLAB Coder). After installation, at the MATLAB command prompt, run mex -setup. You can then use the codegen function to compile your code.

Functions and System Objects That Support Code Generation

Almost all Phased Array System Toolbox functions and System objects are supported for code generation. For a list of supported functions and System objects, see Functions and System Objects Supported for C/C++ Code Generation.

Limitations Specific to Phased Array System Toolbox

Code Generation has the following limitations when used with the Phased Array System Toolbox software:

  • When you employ antennas and arrays that produce polarized fields, the EnablePolarization parameter for these System objects must be set to true:

    This requirement differs from regular MATLAB usage where you can set EnablePolarization property to false even when you use a polarization-enabled antenna. For example, this code uses a polarized antenna, which requires that EnablePolarization property of the phased.Radiator System object™ be set to true.

    function [y] = codegen_radiator()
    sSD = phased.ShortDipoleAntennaElement(...
        'FrequencyRange',[100e6,600e6],'AxisDirection','Y');
    c = physconst('LightSpeed');
    fc = 200e6;
    lambda = c/fc;
    d = lambda/2;
    sURA = phased.URA('Element',sSD,...
        'Size',[3,3],...
        'ElementSpacing',[d,d]);
    sRad = phased.Radiator('Sensor',sURA,...
        'OperatingFrequency',150e6,...
        'CombineRadiatedSignals',true,...
        'EnablePolarization',true);
    x = [1;2;1];
    radiatingAngle = [10;0]; % One angle for one antenna
    y = step(sRad,x,radiatingAngle,eye(3,3));
    

  • Visualization methods for Phased Array System Toolbox System objects are not supported. These methods are pattern, patternAzimuth, patternElevation, plot, plotResponse, and viewArray.

  • When a System object contains another System object as a property value, you must set the contained System object in the constructor. You cannot use Object Property notation to set the property. For example

    antenna = phased.ShortDipoleAntennaElement( ...
        'FrequencyRange',[100e6,600e6],'AxisDirection','Y');
    array = phased.URA('Element',antenna,'Size',[3,3],'ElementSpacing',[0.75,0.75]);
    
    is valid for codegen but
    antenna = phased.ShortDipoleAntennaElement( ...
        'FrequencyRange',[100e6,600e6],'AxisDirection','Y');
    array = phased.URA('Size',[3,3],'ElementSpacing',[0.75,0.75]);
    array.Element = antenna;
    
    is not.

  • Code generation of Phased Array System Toolbox arrays that contain Antenna Toolbox™ antennas is not supported.

  • A list of the limitations on Phased Array System Toolbox functions and System objects is presented here:

    Function or System ObjectLimitation
    plotResponseThis System object method is not supported.
    patternThis System object method is not supported.
    patternAzimuthThis System object method is not supported.
    patternElevationThis System object method is not supported.
    plotThis System object method is not supported.
    viewArrayThis System object method is not supported.
    ambgfunSupported only when output arguments are specified.
    blakechartThis function is not supported.
    pambgfunSupported only when output arguments are specified.
    polsignatureSupported only when output arguments are specified.
    rocpfa
    • Supported only when output arguments are specified.

    • The NonfluctuatingNoncoherent signal type is not supported.

    rocsnr
    • Supported only when output arguments are specified.

    • The NonfluctuatingNoncoherent signal type is not supported.

    stokesSupported only when output arguments are specified.
    phased.ArrayGainThis System object cannot be used with arrays that contain antenna elements that create polarized signals, that is, phased.ShortDipoleAntennaElement or phased.CrossedDipoleAntennaElement
    phased.IntensityScopeThis System object is not supported.
    phased.MatchedFilterThe CustomSpectrumWindow property is not supported.
    phased.RangeDopplerResponseThe CustomRangeWindow and the CustomDopplerWindow properties are not supported.
    phased.ScenarioViewerThis System object is not supported.

General Limitations

Code Generation has some general limitations not specifically related to the Phased Array System Toolbox software. For a more complete discussion, see System Objects in MATLAB Code Generation (MATLAB Coder).

  • The data type and complexity (i.e., real or complex) of any input argument to a function or System object must always remain the same.

  • You cannot pass a System object to any method or function that you made extrinsic using coder.extrinsic.

  • You cannot load a MAT-file using coder.load when it contains a System object. For example, if you construct a System object in the MATLAB environment and save it to a MAT-file

    sSD = phased.ShortDipoleAntennaElement(...
                'FrequencyRange',[0.9e8,2e9],'AxisDirection','Y');
    save x.mat sSD;
    clear sSD;
    then you cannot load the System object in your compiled MEX-file:
    function codegen_load1()
    W = coder.load('x.mat');
    sSD = W.sSD;
    The compilation
    codegen codegen_load1
    will produced an error message: 'Found unsupported class for variable using function 'coder.load'. MATLAB class 'phased.ShortDipoleAntennaElement' found at 'W.sSD' is unsupported.'

    To avoid this problem, you can save the object's properties to a MAT-file, then, use coder.load to load the object properties and re-create the object. For example, create and save a System object’s properties in the MATLAB environment

    sSD = phased.ShortDipoleAntennaElement(...
                'FrequencyRange',[0.9e8,2e9],'AxisDirection','Y');
    FrequencyRange = sSD.FrequencyRange;
    AxisDirection = sSD.AxisDirection;
    save x.mat FrequencyRange AxisDirection;
    

    Then, write a function codegen_load2 to load the properties and create a System object.

    function codegen_load2()
    W = coder.load('x.mat');
    sSD = phased.ShortDipoleAntennaElement(...
        'FrequencyRange',W.FrequencyRange,...
        'AxisDirection',W.AxisDirection);
    Then, issue the commands to create and execute the MEX-file, codegen_load2_mex.
    codegen codegen_load2;
    codegen_load2_mex

  • System object properties are either tunable or nontunable. Unless otherwise specified, System object properties are nontunable. Nontunable properties must be constant. A constant is a value that can be evaluated at compile-time. You can change tunable properties even if the object is locked. Refer to the object's reference page to determine whether an individual property is tunable or not. If you try to set a nontunable System object property and the compiler determines that it is not constant, you will get an error. For example, the phased.URA System object has a nontunable property, ElementSpacing, which sets the distance between elements. You may want to create an array that is tuned to a frequency. You cannot pass in the frequency as an input argument because the frequency must be a constant.

    function [resp] = codegen_const1(fc)
    sSD = phased.ShortDipoleAntennaElement(...
        'FrequencyRange',[100e6,600e6],'AxisDirection','Y');
    c = physconst('LightSpeed');
    lambda = c/fc;
    d = lambda/2;
    sURA = phased.URA('Element',sSD,...
        'Size',[3,3],...
        'ElementSpacing',[d,d]);
    ang = [30;0];
    resp = step(sURA,fc,ang);

    When you codegen this function

    fc = 200e6;
    codegen codegen_const1 -args {fc}

    the compiler responds that the value of the 'ElementSpacing' property, d, is not constant and generates the error message: "Failed to compute constant value for nontunable property 'ElementSpacing'. In code generation, nontunable properties can only be assigned constant values." It is not constant because it depends upon a non-constant variable, fc.

    To correct this problem, set fc to a constant within the function:

    function [resp] = codegen_const2()
    sSD = phased.ShortDipoleAntennaElement(...
        'FrequencyRange',[100e6,600e6],'AxisDirection','Y');
    c = physconst('LightSpeed');
    fc = 200e6;
    lambda = c/fc;
    d = lambda/2;
    sURA = phased.URA('Element',sSD,...
        'Size',[3,3],...
        'ElementSpacing',[d,d]);
    ang = [30;0];
    resp = step(sURA,fc,ang);
    
    and then compile

    codegen codegen_const2
  • You can assign a nontunable System object property value only once before a step method is executed. This requirement differs from MATLAB usage where you can initialize these properties multiple times before the step method is executed.

    This example sets the Size property twice.

    function codegen_property
    sSD = phased.ShortDipoleAntennaElement(...
        'FrequencyRange',[0.9e8,2e9],'AxisDirection','Y');
    sURA = phased.URA('Element',sSD,...
        'Size',[3,3],...
        'ElementSpacing',[0.15,0.15]);
    sURA.Size = [4,4];

    When you issue the command

    codegen codegen_property

    the following error message is produced: "A nontunable property may only be assigned once."

  • In certain cases, the compiler cannot determine the values of nontunable properties at compile time or the code may not even compile. Consider the following example that reads in the x,y,z-coordinates of a 5-element array from a file and then, creates a conformal array System object. The text file, elempos.txt, contains the element coordinates

    -0.5000 -0.2588  0       0.2588  0.5000
    -0.8660 -0.9659 -1.0000 -0.9659 -0.8660
     0       0       0       0       0
    
    The file collectWave.m contains reads the element coordinates and creates the object.
    function y = collectWave(angle)
    elPos = calcElPos;
    cArr = phased.ConformalArray('ElementPosition',elPos);
    y = collectPlaneWave(cArr,randn(4,2),angle,1e8);
    end
    
    function elPos = calcElPos
    fid = fopen('elempos.txt','r');
    el = textscan(fid, '%f');
    n = length(el{1});
    nelem = n/3;
    fclose(fid);
    elPos = reshape(el{1},nelem,3).';
    end
    Attempting to compile
    codegen collectWave -args {[10 30]}
    produces the error "Permissions 'r' and 'r+' are not supported".

    The following example is a work-around that uses coder.extrinsic and coder.const to insure that the value for the nontunable property, 'ElementPosition', is a compile time constant. The function in the file, collectWave1.m, creates the object using the calcElPos function. This function runs inside the MATLAB interpreter at compile time.

    function y = collectWave1(angle)
    coder.extrinsic('calcElPos')
    elPos = coder.const(calcElPos);
    cArr = phased.ConformalArray('ElementPosition',elPos);
    y = collectPlaneWave(cArr,randn(4,2),angle,1e8);
    end
    The file calcElPos.m loads the element positions from the text file

    function elPos = calcElPos
    fid = fopen('elempos.txt','r');
    el = textscan(fid, '%f');
    n = length(el{1});
    nelem = n/3;
    fclose(fid);
    elPos = reshape(el{1},nelem,3).';

    Only the collectWave1.m file is compiled with codegen. Compiling and running

    codegen collectWave1 -args {[10 30]}
    collectWave1_mex([10,30])
    will succeed.

    An alternate work-around uses coder.load to insure that the value of the nontunable property 'ElementPosition' is compile-time constant. In the MATLAB environment, run calcElPos2 to save the array coordinates contained in elempos.txt to a MAT-file. Then, load the contents of the MAT-file within the compiled code.

    function calcElPos2
    fid = fopen('elempos.txt');
    el = textscan(fid, '%f');
    fclose(fid);
    elPos = reshape(el{1},[],3).';
    save('positions', 'elPos');
    end
    The file collectWave2.m loads the coordinate positions and creates the conformal array object
    function y = collectWave2(angle)
    var = coder.load('positions');
    cArr = phased.ConformalArray('ElementPosition',var.elPos);
    y = collectPlaneWave(cArr,randn(4,2),angle,1e8);
    end
    Only the collectWave2.m file is compiled with codegen. Compiling and running collectWave2.m
    codegen collectWave2 -args {[10 30]}
    collectWave2_mex([10,30])
    will succeed. This second approach is more general than the first since a MAT-file can contain any variables, except System objects.

  • The System object clone method is not supported.

Limitations for System Objects that Require Dynamic Memory Allocation

System objects that require dynamic memory allocation cannot be used for code generation in the following cases:

Inside a MATLAB Function block in a Simulink® model.
Inside a MATLAB function in a Stateflow® chart.
When using MATLAB as the action language in a Stateflow chart.
Inside a Truth Table block in a Simulink model.
Inside a MATLAB System block (except for normal mode).
When using Simulink Coder for code generation.
When using MATLAB Coder for code generation and dynamic memory allocation is disabled.