在 C/C++ 仿真期间,阵列可能引发各种问题,即使在执行综合步骤前也是如此。如果您指定的阵列过大,可能导致 C/C++ 仿真因存储器不足而失败,如以下示例所示:
#include "ap_int.h"
int i, acc;
// Use an arbitrary precision type
ap_int<32> la0[10000000], la1[10000000];
for (i=0 ; i < 10000000; i++) {
acc = acc + la0[i] + la1[i];
}
仿真可能因存储器不足而失败,因为阵列置于存储器中存在的栈上,而不是置于由操作系统管理并且可使用本地磁盘空间来扩展的堆上。某些问题可能提高出现此问题的概率:
- 在 PC 上,可用存储器通常小于大型 Linux 系统,并且可用存储器可能进一步减少。
- 如以上示例所示,使用任意精度类型可能使此问题更严重,因为这些类型建模时所需存储器比标准 C/C++ 类型所需存储器更多。
- 使用 C/C++ 中的更复杂的定点任意精度类型可能还会提高设计出现存储器不足问题的概率,因为各类型所需存储器更多。
增加 C/C++ 代码开发中的存储器资源的标准方法是使用连接器选项增大栈大小,例如以下选项将栈大小显式设置为 syn.csimflags -z
stack-size=10485760
。
但机器可能没有足够存储器可用,且增大栈大小无效。在此情况下,解决方案是使用动态存储器分配执行仿真,但使用固定大小的阵列执行综合,如以下示例所示。这意味着此操作所需存储器将在堆上进行分配,且此堆由操作系统管理并可使用本地磁盘空间来扩展。
#include "ap_int.h"
int i, acc;
#ifdef __SYNTHESIS__
// Use an arbitrary precision type & array for synthesis
ap_int<32> la0[10000000], la1[10000000];
#else
// Use an arbitrary precision type & dynamic memory for simulation
ap_int<32> *la0 = malloc(10000000 * sizeof(ap_int<32>));
ap_int<32> *la1 = malloc(10000000 * sizeof(ap_int<32>));
#endif
for (i=0 ; i < 10000000; i++) {
acc = acc + la0[i] + la1[i];
}
但这并非理想解决方案,因为仿真的代码与综合的代码不同。但这是完成仿真的唯一途径。如果您采用此方法,请务必确认 C/C++ 测试激励文件涵盖阵列访问的各方面。由 cosim_design
执行的 RTL 仿真将验证综合后的代码中执行的存储器访问是否正确。
注释:
__SYNTHESIS__
宏仅限在要综合的代码上使用。请勿在测试激励文件中使用该宏,因为在 C/C++ 语言仿真或 C/C++ RTL 协同仿真中,该宏无关紧要。请参阅
Vitis-HLS-Introductory-Examples/Pipelining/Functions/hier_func
以获取此示例的完整版本。