FAQ: Why does Fixed-Point fi variable times MATLAB floating-point variable error out in code generation, MATLAB Function Block, etc.?
8 views (last 30 days)
Show older comments
MathWorks Fixed Point Team
on 22 Dec 2023
Edited: Andy Bartlett
on 2 Jan 2024
FAQ: Why does Fixed-Point fi variable multiplied by a MATLAB floating-point variable error out in code generation, MATLAB Function Block, etc.?
When simulating with base MATLAB, it works fine.
But when using codegen command, Simulink's MATLAB function block, I get an error like the following.
In fi .* non-fi, or non-fi .* fi, the non-fi must be a constant.
0 Comments
Accepted Answer
Andy Bartlett
on 22 Dec 2023
Edited: Andy Bartlett
on 2 Jan 2024
fi op float: auto convert float to fixed-point "constant"
Fixed-Point Designer's fi variables are designed to prioritize ease of creating an algorithm that is 100% fixed-point.
When authoring an algorithm, it is very convenient to be able to simply enter constants using their "ideal" decimal value.
y = 0.789 * u
Fixed-Point Designer fi variables seek to support that significant convenience AND achieve the goal of getting a 100% fixed-point algorithm.
By MATLAB language rules, the literal constant 0.789 is a floating-point double. But if the other variable in a binary (i.e. two input) operation is a fi variable, then fi handles the operation according to "Fixed-Point Designer fi rules."
These rules say to treat the other input as if it was a constant, and convert that constant to a fixed-point type in a sensible way for the specific operation being performed.
For multiplication, the rule says convert the "constant" to a fixed-point type with the same word length and signedness as the fixed-point argument. Automatically decide the scaling of the constant to give the maximum precision representation of the value using the given signedness and word length. This is known as "Best Precision Scaling."
Using this rule, line below computing y1 implicitly behaves the same as the more explicit line computing y2
u = fi(123.45, 1,16,7)
y1 = u * 0.789
y2 = u * fi(0.789, 1,16)
isSame = y1 == y2
If value changes enough, data types can change
A weakness of the fi-op-float design is that if the floating-point variable isn't really constant, then the data type of the constant may change, and data type of the output may change to.
Notice that when the following code is executed, the data type of y changes in the third iteration.
kVec = [0.789, 0.65, 6.54];
u = fi(123.45, 1,16,7);
for i=1:length(kVec)
y = u * kVec(i)
end
In an algorithm running on a real-time embedded system, it is not practical to change data types on the fly. Too costly and too slow. An algorithm is not ready for practical embedded deployment until all the numeric data types are locked down.
Code generation "hates" if data types might change
Code generation has a hard rule that the numeric data type of a variable must NOT change.
MathWorks code generation technology used by MATLAB Coder, Simulink accelerator, MATLAB Function Blocks, etc. will apply sophisticated analysis techniques seeking to prove that a data type will NOT change. If it can prove that, the code generation process happily continues.
When MathWorks code generation technology sees a literal constant times a fi variable,
y = 0.789 * u
it easily proves to itself that data type for the constant and for y will not change and is happy.
But if the other term is presented as a variable,
y = otherVar * u
then code generation technology will have to work much harder to prove that the data types do NOT change.
That analysis may fail to prove no data type changes. Moreover, it may be that otherVar really is a variable and not a constant.
The code generation technology will throw an error if it can't prove constantness with a message such as
In fi .* non-fi, or non-fi .* fi, the non-fi must be a constant.
Three paths to code generation happiness
When constantness analysis does not succceed, there are three paths to making the code generation technology happy about data type constness.
1) One path is to explicitly inform the tools that a variable is actually constant.
See the help of these utilities for techniques.
help coder.Constant
help coder.const
2) A second path is to explicitly cast the other variable to a fully defined fixed-point type.
% Solution 1
% explictly define the vector to be fixed-point
%
kVec = fi( [0.789, 6.54], 0, 16 );
u = fi(123.45, 1,16,7);
for i=1:length(kVec)
y = u * kVec(i)
end
or
% Solution 2
kVecDbl = [0.789, 6.54];
u = fi(123.45, 1,16,7);
for i=1:length(kVec)
% cast the floating-point variable at run-time
currentK = fi( kVecDbl(i), 1, 16, 11 )
y = u * currentK
end
3) A third path is to do the math in floating-point.
If the other argument to the operation really should be a floating-point variable in the embedded design, then doing the math in floating-point may be preferable.
Simulink blocks like Product follow a default rule similar to the C language. If one of the input arguments to a operation is floating-point, then the biggest floating-point type wins. So in double precision floating-point times fixed-point, double is used for the operation and the output. In fixed-point times single precision floating-point, single is used for the operation and the output.
To do this in MATLAB code involving fi variables, you need to insert an explicit cast of the fi variable to the desired floating-point type.
% Solution 3
kVec = single( [0.789, 6.54] );
u = fi(123.45, 1,16,7);
% simple approach
% u2 = single(u);
% Fancy approach automatically adapting to type of kVec
% using Cast-Like technique
%
if isfloat(kVec)
u2 = cast(u, 'like', kVec);
else
u2 = u;
end
for i=1:length(kVec)
y = u2 * kVec(i)
end
0 Comments
More Answers (0)
See Also
Categories
Find more on Floating-Point to Fixed-Point Conversion in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!