Undefined Behaviors - 2023.2 English

Vitis High-Level Synthesis User Guide (UG1399)

Document ID
Release Date
2023.2 English

The C/C++ undefined behaviors may lead to a different behavior in simulation and synthesis. An example of this behavior is shown below:

for (int i=0; i<N; i++) {
  int val; // uninitialized value
  if (i==0) val=0;
  else if (cond) val=1;
  // val may have indeterminate value here
  A[i] = val; // undefined behavior
  val++; // dead code

In the above example you should not expect that A[i] gets the value of val from the previous loop iteration if neither i==0, nor (cond) are true. You should even not expect that the increment (val++) will happen. The same is true for scalars values obtained after complete partition.

For such C/C++ undefined behavior situations, the behavior between GCC and Vitis HLS when compiling code is likely to be different, which will lead to a mismatch during RTL/Co-simulation. This is because in GCC, compiled for CPU, val is often left in the same register or in the same stack location across loop iterations, and therefore the behavior is that the value of val is retained between loop iterations.

The solution is either to initialize val at each iteration (if this is the expected behavior) or to move the declaration of val above the loop, as high as necessary, so that its lifetime scope matches the intent reuse. You should not expect that the compiler will infer a specific defined RTL behavior from an undefined C/C++ behavior.