cgvModel = 'Isolated'; % Configure the model cgvCfg = cgv.Config( cgvModel, 'Connectivity', 'sil') cgvCfg.configModel(); % Execute the simulation cgvSim = cgv.CGV( cgvModel, 'Connectivity', 'sim') result1 = cgvSim.run() % Execute the generated code cgvSil = cgv.CGV( cgvModel, 'Connectivity', 'sil') result2 = cgvSil.run() % Get the output data simData = cgvSim.getOutputData(1); silData = cgvSil.getOutputData(1); % Compare results [matchNames, ~, mismatchNames, ~] = ... cgv.CGV.compare( simData, silData, 'Plot', 'mismatch')
At the completion of this script, the following figure appeared, confirming that the results from the generated code are different from the simulation.
Identify the origin of the difference
To identify the origin of the difference, I enabled logging for more signals in the model. After a few iterations, without modifying the above script I identified the following subsystem where the input was identical, but the output was different:
When looking at the generated code, I found out that the line for this subsystem is:
(*rty_Out2) = 400.0F * (*rtu_In1) * 100.0F;
I made a quick test and manually changed the code to:
tmp = 400.0F * (*rtu_In1);
(*rty_Out2) = tmp * 100.0F;
Surprisingly, this modified code produces results identical to simulation!
Consult an expert
I have to admit, I had no idea how these two similar codes could lead to different results, so I asked one of our experts in numerical computation.
I learned that some compilers use a technology called extended precision. With this technology, when you have a line of code including more than one operation, the compiler can use a larger container to store intermediary results. The goal of this technology is to provide more accurate results, however in this case it also leads to surprises.
After understanding this behavior, we recommended to the user a few options to avoid this type of expression folding in the generated code and consequently avoid this behavior of the compiler.
Without the Code Generation Verification API, I would have spent a lot of time wiring debugging signals in the model. This tool helped me to quickly identify the root cause of the problem without modifying the model. Note that the CGV API can do a lot more than what I showed here. Look at the CGV documentation for more details.
Now it's your turn
How do you verify that the generated code is numerically equivalent to your model? Leave a comment here.