MATLAB: How to get rid of red OVFL outside PolySpace For Model Link TL

-post-preprocessing-commandctoovflPolyspace Model Link TL

When code has been generated using TargetLink and the CTO option has been enabled, you can find in the generated code something like:
S16_C = ((Int16) ((/* CTO */ (UInt16) S16_A) + ( /* CTO */ (UInt16) S16_B)));
Even it has been intentionally generated, using PolySpace, this code leads to an orange or red overflow on the (int16) cast depending on the values of A and B. Verifying this code inside PolySpace For Model Link TL, you have no red/orange checks but get an orange or red outside.

Best Answer

CTO means Compute Through Overflow and you will find some documentation in the dSPACE documentation about the justification of this CTO, and notably using this link:
- Mark Compute-Through-Overflow (CTO)
TargetLink supports the ‘compute-through-overflow’ calculation method, which avoids computations in unnecessary word lengths. Calculations that are computed using this method can optionally be marked by a code comment ("/* CTO */") in the generated code.
To make the Code Generator insert code comments, use the command line option "PolyspaceSupport" in the tl_pre_codegen_hook.m file. This allows you to distinguish between CTOs used intentionally by TargetLink and possible overflow errors introduced by improper scaling or signal range specification.
So in summary, the orange or red check OVFL put by PolySpace is justified. A way to get rid of this orange/red OVFL outside PolySpace For Model Link TL is to use the following -post-preprocessing-command option (ppc) written in Perl language:
#!/usr/bin/perl
binmode STDOUT;
while ($line = <STDIN>)
{
# Replace /* CTO */ (UINT8) ... with /* CTO (UINT8) */
$line =~ s/(\/\*\s+CTO\s+)\*\/(\s*\(\w+\))/$1$2\*\//mg;
# Replace the rounded float max with the real value representative
# so errors are not produced with the -ignore-float-rounding option
$line =~ s/3\.40282347e\+038F/3\.402823466e38F/mg;
# Output the line
print $line;
}
Using this ppc, the code gets replaced by:
S16_C = ((Int16) ((/* CTO (UInt16) */ S16_A) + ( /* CTO (UInt16) */ S16_B)));
So it allows to get rid of the promotion from a signed value to an unsigned value when values fit same memory size. In addition, it gets rid of the bad rounded float max value which could be available in standard headers.