C/C++ 未定义的行为可能导致仿真与综合中出现不同的行为。此类行为的示例如下所示:
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
}
在以上示例中,只要 i==0
和 (cond)
值均非 true,A[i] 就不应从上一次循环迭代得到 val 值。甚至不应发生递增 (val++
)。对于完成分区后获取的标量值也同样如此。
对于此类 C/C++ 未定义的行为,编译代码时,GCC 与 Vitis HLS 之间的行为可能有别,这可能导致 RTL/协同仿真期间发生不匹配。这是由于在为 CPU 编译的 GCC 中,通常不同循环迭代之间的 val
保留在相同寄存器或栈位置,因此不同循环迭代之间的行为是 val
保留不变。
解决方案是在每次迭代时初始化 val(前提是,此行为与期望相符)或者将 val
的声明移至循环上层(尽可能高),使其生存期范围与所需复用相符。编译器不应根据未定义的 C/C++ 行为来推断已定义的特定 RTL 行为。