Main Content

Control the Generation of Fixed-Point Utility Functions

Optimize Generated Code Using Specified Minimum and Maximum Values

The Fixed-Point Designer™ software uses representable minimum and maximum values and constant values to determine if it is possible to optimize the generated code, for example, by eliminating unnecessary utility functions and saturation code from the generated code.

This optimization results in:

  • Reduced ROM and RAM consumption

  • Improved execution speed

When you select the Optimize using specified minimum and maximum values configuration parameter, the software takes into account input range information, also known as design minimum and maximum, that you specify for signals and parameters in your model. It uses these minimum and maximum values to derive range information for downstream signals in the model and then uses this derived range information to simplify mathematical operations in the generated code whenever possible.

Prerequisites

The Optimize using specified minimum and maximum values parameter appears for ERT-based targets only and requires an Embedded Coder® license when generating code.

How to Configure Your Model

To make optimization more likely:

  • Provide as much design minimum and maximum information as possible. Specify minimum and maximum values for signals and parameters in the model for:

    • Inport and Outport blocks

    • Block outputs

    • Block inputs, for example, for the MATLAB Function and Stateflow® Chart blocks

    • Simulink.Signal objects

  • Before generating code, test the minimum and maximum values for signals and parameters. Otherwise, optimization might result in numerical mismatch with simulation. You can simulate your model with simulation range checking enabled. If errors or warnings occur, fix these issues before generating code.

     How to Enable Simulation Range Checking

  • Use fixed-point data types with binary-point-only (power-of-two) scaling.

  • Provide design minimum and maximum information upstream of blocks as close to the inputs of the blocks as possible. If you specify minimum and maximum values for a block output, these values are most likely to affect the outputs of the blocks immediately downstream. For more information, see Eliminate Unnecessary Utility Functions Using Specified Minimum and Maximum Values.

How to Enable Optimization

  1. In the Configuration Parameters dialog box, set the Code Generation > System target file to select an Embedded Real-Time (ERT) target (requires an Embedded Coder license).

  2. Specify design minimum and maximum values for signals and parameters in your model using the tips in How to Configure Your Model.

  3. Select the Optimization > Advanced parameters > Optimize using the specified minimum and maximum values configuration parameter.

Limitations

  • This optimization does not occur for:

    • Multiword operations

    • Fixed-point data types with slope and bias scaling

    • Addition unless the fraction length is zero

  • This optimization does not take into account minimum and maximum values for:

    • Merge block inputs. To work around this issue, use a Simulink.Signal object on the Merge block output and specify the range on this object.

    • Bus elements.

    • Conditionally executed subsystem (such as a triggered subsystem) block outputs that are directly connected to an Outport block.

      Outport blocks in conditionally executed subsystems can have an initial value specified for use only when the system is not triggered. In this case, the optimization cannot use the range of the block output because the range might not cover the initial value of the block.

  • There are limitations on precision because you specify the minimum and maximum values as double-precision values. If the true value of a minimum or maximum value cannot be represented as a double, ensure that you round the minimum and maximum values correctly so that they cover the true design range.

  • If your model contains multiple instances of a reusable subsystem and each instance uses input signals with different specified minimum and maximum values, this optimization might result in different generated code for each subsystem so code reuse does not occur. Without this optimization, the Simulink Coder™ software generates code once for the subsystem and shares this code among the multiple instances of the subsystem.

Eliminate Unnecessary Utility Functions Using Specified Minimum and Maximum Values

This example shows how the Fixed-Point Designer software uses the input range for a division operation to determine whether it can eliminate unnecessary utility functions from the generated code. It uses the fxpdemo_min_max_optimization model. First, you generate code without using the specified minimum and maximum values to see that the generated code contains utility functions to ensure that division by zero does not occur. You then turn on the optimization, and generate code again. With the optimization, the generated code does not contain the utility function because it is not necessary for the input range.

Generate Code Without Using Minimum and Maximum Values

First, generate code without taking into account the design minimum and maximum values for the first input of the division operation to show the code without the optimization. In this case, the software uses the representable ranges for the two inputs, which are both uint16. With these input ranges, it is not possible to implement the division with the specified precision using shifts, so the generated code includes a division utility function.

  1. Run the example. At the MATLAB® command line, enter:

    openExample('fixedpoint/FixedPointOptimizationsUsingSpecifiedMinAndMaxValuesExample')

  2. In the example window, double-click the View Optimization Configuration button.

    The Optimization pane of the Configuration Parameters dialog box appears.

    Note that the Optimize using specified minimum and maximum values parameter is not selected.

  3. Double-click the Generate Code button.

    The code generation report appears.

  4. In the model, right-click the Division with increased fraction length output type block.

    The context menu appears.

  5. From the context menu, select C/C++ Code > Navigate To C/C++ Code.

    The code generation report highlights the code generated for this block. The generated code includes a call to the div_repeat_u32 utility function.

    rtY.Out3 = div_repeat_u32((uint32_T)rtU.In5 << 16, 
      (uint32_T)rtU.In6, 1U);

  6. Click the div_repeat_u32 link to view the utility function, which contains code for handling division by zero.

Generate Code Using Minimum and Maximum Values

Next, generate code for the same division operation, this time taking into account the design minimum and maximum values for the first input of the Product block. These minimum and maximum values are specified on the Inport block directly upstream of the Product block. With these input ranges, the generated code implements the division by simply using a shift. It does not need to generate a division utility function, reducing both memory usage and execution time.

  1. Double-click the Inport block labeled 5 to open the block parameters dialog box.

  2. On the block parameters dialog box, select the Signal Attributes pane and note that:

    • The Minimum value for this signal is 1.

    • The Maximum value for this signal is 100.

  3. Click OK to close the dialog box.

  4. Double-click the View Optimization Configuration button.

    The Optimization pane of the Configuration Parameters dialog box appears.

  5. On this pane, select the Optimize using specified minimum and maximum values parameter and click Apply.

  6. Double-click the Generate Code button.

    The code generation report appears.

  7. In the model, right-click the Division with increased fraction length output type block.

    The context menu appears.

  8. From the context menu, select C/C++ Code > Navigate To C/C++ Code.

    The code generation report highlights the code generated for this block. This time, the generated code implements the division with a shift operation and there is no division utility function.

    tmp = rtU.In6;
    rtY.Out3 = (uint32_T)tmp == 
      (uint32_T)0 ? MAX_uint32_T : ((uint32_T)rtU.In5 << 17) /
        (uint32_T)tmp;

Modify the Specified Minimum and Maximum Values

Finally, modify the minimum and maximum values for the first input to the division operation so that its input range is too large to guarantee that the value does not overflow when shifted. Here, you cannot shift a 16-bit number 17 bits to the right without overflowing the 32-bit container. Generate code for the division operation, again taking into account the minimum and maximum values. With these input ranges, the generated code includes a division utility function to ensure that no overflow occurs.

  1. Double-click the Inport block labelled 5 to open the block parameters dialog box.

  2. On the block parameters dialog box, select the Signal Attributes pane and set the Maximum value to 40000, then click OK to close the dialog box.

  3. Double-click the Generate Code button.

    The code generation report appears.

  4. In the model, right-click the Division with increased fraction length output type block.

    The context menu appears.

  5. From the context menu, select C/C++ Code > Navigate To C/C++ Code.

    The code generation report highlights the code generated for this block. The generated code includes a call to the div_repeat_32 utility function.

    rtY.Out3 = div_repeat_u32((uint32_T)rtU.In5 << 16, 
      (uint32_T)rtU.In6, 1U);