Main Content

Generated Fixed-Point Code

Location of Generated Fixed-Point Files

By default, the fixed-point conversion process generates files in a folder named codegen/fcn_name/fixpt in your local working folder. fcn_name is the name of the MATLAB® function that you are converting to fixed point.

File nameDescription
fcn_name_fixpt.m

Generated fixed-point MATLAB code.

To integrate this fixed-point code into a larger application, consider generating a MEX-function for the function and calling this MEX-function in place of the original MATLAB code.

fcn_name_fixpt_exVal.mat

MAT-file containing:

  • A structure for the input arguments.

  • The name of the fixed-point file.

fcn_name_fixpt_report.html

Link to the type proposal report that displays the generated fixed-point code and the proposed type information.

fcn_name_report.html

Link to the type proposal report that displays the original MATLAB code and the proposed type information.

fcn_name_wrapper_fixpt.m

File that converts the floating-point data values supplied by the test file to the fixed-point types determined for the inputs during the conversion step. These fixed-point values are fed into the converted fixed-point function, fcn_name_fixpt.

Minimizing fi-casts to Improve Code Readability

The conversion process tries to reduce the number of fi-casts by analyzing the floating-point code. If an arithmetic operation is comprised of only compile-time constants, the conversion process does not cast the operands to fixed point individually. Instead, it casts the entire expression to fixed point.

For example, here is the fixed-point code generated for the constant expression x = 1/sqrt(2) when the selected word length is 14.

Original MATLAB CodeGenerated Fixed-Point Code

x = 1/sqrt(2);

x = fi(1/sqrt(2), 0, 14, 14, fm);

fm is the local fimath.

Avoiding Overflows in the Generated Fixed-Point Code

The conversion process avoids overflows by:

  • Using full-precision arithmetic unless you specify otherwise.

  • Avoiding arithmetic operations that involve double and fi data types. Otherwise, if the word length of the fi data type is not able to represent the value in the double constant expression, overflows occur.

  • Avoiding overflows when adding and subtracting non fixed-point variables and fixed-point variables.

    The fixed-point conversion process casts non-fi expressions to the corresponding fi type.

    For example, consider the following MATLAB algorithm.

    % A = 5;
    % B = ones(300, 1)
    function y = fi_plus_non_fi(A, B)
      % '1024' is non-fi, cast it
      y = A + 1024;
      % 'size(B, 1)*length(A)' is a non-fi, cast it
      y = A + size(B, 1)*length(A);
    end

    The generated fixed-point code is:

    %#codegen
    % A = 5;
    % B = ones(300,1)
    function y = fi_plus_non_fi_fixpt(A,B)
      % '1024' is non-fi, cast it
      fm = fimath('RoundingMethod','Floor',...
          'OverflowAction','Wrap',...
          'ProductMode','FullPrecision',...
          'MaxProductWordLength',128,...
          'SumMode','FullPrecision',...
          'MaxSumWordLength',128);
    
      y = fi(A + fi(1024,0,11,0,fm),0,11,0,fm);
      % 'size(B, 1)*length(A)' is a non-fi, cast it
      y(:) = A + fi(size(B,fi(1,0,1,0,fm))*length(A),0,9,0,fm);
    end

Controlling Bit Growth

The conversion process controls bit growth by using subscripted assignments, that is, assignments that use the colon (:) operator, in the generated code. When you use subscripted assignments, MATLAB overwrites the value of the left-hand side argument but retains the existing data type and array size. Using subscripted assignment keeps fixed-point variables fixed point rather than inadvertently turning them into doubles. Maintaining the fixed-point type reduces the number of type declarations in the generated code. Subscripted assignment also prevents bit growth which is useful when you want to maintain a particular data type for the output.

Avoiding Loss of Range or Precision

Avoiding Loss of Range or Precision in Unsigned Subtraction Operations

When the result of the subtraction is negative, the conversion process promotes the left operand to a signed type.

For example, consider the following MATLAB algorithm.

% A = 1;
% B = 5
function [y,z] = unsigned_subtraction(A,B)
  y = A - B;
  
  C = -20;
  z = C - B;
end

In the original code, both A and B are unsigned and the result of A-B can be negative. In the generated fixed-point code, A is promoted to signed. In the original code, C is signed, so does not require promotion in the generated code.

%#codegen
% A = 1;
% B = 5
function [y,z] = unsigned_subtraction_fixpt(A,B)
 
fm = fimath('RoundingMethod','Floor',...
    'OverflowAction','Wrap',...
    'ProductMode','FullPrecision',...
    'MaxProductWordLength',128,...
    'SumMode','FullPrecision',...
    'MaxSumWordLength',128);
y = fi(fi_signed(A) - B,1,3,0,fm);
C = fi(-20,1,6,0,fm);
z = fi(C - B,1,6,0,fm);
end
 
 
function y = fi_signed(a)
coder.inline('always');
if isfi(a) && ~(issigned(a))
  nt = numerictype(a);
  new_nt = numerictype(1,nt.WordLength + 1,nt.FractionLength);
  y = fi(a,new_nt,fimath(a));
else
  y = a;
end
end

Avoiding Loss of Range When Concatenating Arrays of Fixed-Point Numbers

If you concatenate matrices using vertcat and horzcat, the conversion process uses the largest numerictype among the expressions of a row and casts the leftmost element to that type. This type is then used for the concatenated matrix to avoid loss of range.

For example, consider the following MATLAB algorithm.

% A = 1, B = 100, C = 1000
function [y, z] = lb_node(A, B, C)
  %% single rows
  y = [A B C];
  %% multiple rows
  z = [A 5; A B; A C];
end

In the generated fixed-point code:

  • For the expression y = [A B C], the leftmost element, A, is cast to the type of C because C has the largest type in the row.

  • For the expression [A 5; A B; A C]:

    • In the first row, A is cast to the type of C because C has the largest type of the whole expression.

    • In the second row, A is cast to the type of B because B has the larger type in the row.

    • In the third row, A is cast to the type of C because C has the larger type in the row.

%#codegen
% A = 1, B = 100, C = 1000
function [y,z] = lb_node_fixpt(A,B,C)
  %% single rows
  fm = fimath('RoundingMethod','Floor',...
      'OverflowAction','Wrap',...
      'ProductMode','FullPrecision',...
      'MaxProductWordLength',128,...
      'SumMode','FullPrecision',...
      'MaxSumWordLength',128);

  y = fi([fi(A,0,10,0,fm) B C],0,10,0,fm);
  
  %% multiple rows
  z = fi([fi(A,0,10,0,fm) 5; ...
      fi(A,0,7,0,fm) B; ...
      fi(A,0,10,0,fm) C],0,10,0,fm);
end

Handling Non-Constant mpower Exponents

If the function that you are converting has a scalar input, and the mpower exponent input is not constant, the conversion process sets the fimath ProductMode to SpecifyPrecision in the generated code. With this setting , the output data type can be determined at compile time.

For example, consider the following MATLAB algorithm.

% a = 1
% b = 3
function y = exp_operator(a, b)
  % exponent is a constant so no need to specify precision
  y = a^3;
  % exponent is not a constant, use 'SpecifyPrecision' for 'ProductMode'
  y = b^a;
end

In the generated fixed-point code, for the expression y = a^3 , the exponent is a constant, so there is no need to specify precision. For the expression, y = b^a, the exponent is not constant, so the ProductMode is set to SpecifyPrecision.

%#codegen
% a = 1
% b = 3
function y = exp_operator_fixpt(a,b)
  % exponent is a constant so no need to specify precision
  fm = fimath('RoundingMethod','Floor',...
      'OverflowAction','Wrap',...
      'ProductMode','FullPrecision',...
      'MaxProductWordLength',128,...
      'SumMode','FullPrecision',...
      'MaxSumWordLength',128);

  y = fi(a^3,0,2,0,fm);
  % exponent is not a constant, use 'SpecifyPrecision' for 'ProductMode'
  y(:) = fi(b,'ProductMode','SpecifyPrecision',...
      'ProductWordLength',2,...
      'ProductFractionLength',0)^a;
end