引发的c/rtl协同仿真异常)
一、注意问题出现阶段1.下属异常代码在C综合阶段功能是正确的2.下属异常代码在RTL综合阶段是能够正常综合的3.下属异常代码在RTL综合后进行C/RTL协同仿真是失败的。一、if(j 0)引发的c/rtl协同仿真代码案例一void fuction(){static ap_uint24 win_buff[10];#pragma HLS ARRAY_PARTITION variablewin_buff complete dim0for(ap_uint16 i0; iheight; i) {for(ap_uint16 j0; j(cols1); j) {#pragma HLS pipeline II1srctemp src.read();// 错误代码 for(ap_uint4 k 0; k 10; k) {#pragma HLS UNROLLif(j0){win_buff[k] srctemp;win_buff[k 1] srctemp;win_buff[k 2] srctemp;win_buff[k 3] srctemp;win_buff[k 4] srctemp;}else{win_buff[k] win_buff[k 1];win_buff[k 1] win_buff[k 2];win_buff[k 2 win_buff[k 3];win_buff[k 3] win_buff[k 4];win_buff[k 4] srctemp;}}// }}}二、if(j 0)引发的c/rtl协同仿真代码案例二void fuction(){static ap_uint24 win_buff[10];#pragma HLS ARRAY_PARTITION variablewin_buff complete dim0for(ap_uint16 i0; iheight; i) {for(ap_uint16 j0; j(cols1); j) {#pragma HLS pipeline II1srctemp src.read();// 错误代码 if(j0){for(ap_uint4 k 0; k 10; k) {#pragma HLS UNROLLwin_buff[k] srctemp;win_buff[k 1] srctemp;win_buff[k 2] srctemp;win_buff[k 3] srctemp;win_buff[k 4] srctemp;}}else{for(ap_uint4 k 0; k 10; k) {#pragma HLS UNROLLwin_buff[k] win_buff[k 1];win_buff[k 1] win_buff[k 2];win_buff[k 2] win_buff[k 3];win_buff[k 3] win_buff[k 4];win_buff[k 4] srctemp;}}// }}}三、正确的案例void fuction(){static ap_uint24 win_buff[10];#pragma HLS ARRAY_PARTITION variablewin_buff complete dim0for(ap_uint16 i0; iheight; i) {for(ap_uint16 j0; j(cols1); j) {#pragma HLS pipeline II1srctemp src.read();// 错误代码 for(ap_uint4 k 0; k 10; k) {#pragma HLS UNROLLwin_buff[k] win_buff[k 1];win_buff[k 1] win_buff[k 2];win_buff[k 2] win_buff[k 3];win_buff[k 3] win_buff[k 4];win_buff[k 4] srctemp;}// }}}四、失败的原因分析1.失败的日志Vivado Simulator 2018.3ERROR: [Simtcl 6-50] Simulation engine failed to start: Failed to launch child process (child exe not found).Please see the Tcl Console or the Messages for details.ERROR: [COSIM 212-303] Aborting co-simulation: RTL simulation failed.ERROR: [COSIM 212-344] Rtl simulation failed.INFO: [COSIM 212-211] II is measurable only when transaction number is greater than 1 in RTL simulation. Otherwise, they will be marked as all NA. If user wants to calculate them, please make sure there are at least 2 transactions in RTL simulation.could not read xxx/solution1/sim/tv/rtldatafile/sim/report/cosim.log: no such file or directorywhile executingsource xxx/solution1/cosim.tclinvoked from withinhls::main xxx/solution1/cosim.tcl(uplevel body line 1)invoked from withinuplevel 1 hls::main {*}$args(procedure hls_proc line 5)invoked from withinhls_proc $argvFinished C/RTL cosimulation.这段异常从因为日志看是说综合工具和综合工具仿真器有问题或者是环境设置有问题推荐电脑重启或者关机或者重新安装软件。我试了试这些方法都不行实际上我发现就是那个if j0那段代码造成的异常。后面仔细分析了一下是这段代码片剖坏了移位寄存器功能造成综合工具在仿真的时候出现了二义性从而报错。2.失败的原因分析上述失败代码中if(j 0) 不是简单加了一个边界判断而是破坏了 HLS 原代码的规则移位寄存器结构和流水线时序导致 C 综合/RTL 生成失败最终 C/RTL 仿真启动时找不到 RTL 仿真可执行文件。五、去掉static修饰wind_buffer也可也解决问题void fuction(){// static ap_uint24 win_buff[10];//c/rtl协同仿真异常static ap_uint24 win_buff[10];//c/rtl协同仿真正常#pragma HLS ARRAY_PARTITION variablewin_buff complete dim0for(ap_uint16 i0; iheight; i) {for(ap_uint16 j0; j(cols1); j) {#pragma HLS pipeline II1srctemp src.read();// 错误代码 if(j0){for(ap_uint4 k 0; k 10; k) {#pragma HLS UNROLLwin_buff[k] srctemp;win_buff[k 1] srctemp;win_buff[k 2] srctemp;win_buff[k 3] srctemp;win_buff[k 4] srctemp;}}else{for(ap_uint4 k 0; k 10; k) {#pragma HLS UNROLLwin_buff[k] win_buff[k 1];win_buff[k 1] win_buff[k 2];win_buff[k 2] win_buff[k 3];win_buff[k 3] win_buff[k 4];win_buff[k 4] srctemp;}}// }}}static修饰win buffer造成win buffer是移位寄存器并且初始化在bitstream加载过程初始化然后if的两种判断破坏了结构去掉static后变成普通的变量设计就变得正确了。这个试验是个很好的案例我差不多花费了一个小时才把这段逻辑推导成功和分析明白。六、总结1.当使用 static 修饰时HLS 认为 win_buff 是一个持久状态变量需要在 FPGA 上电或复位时恢复到特定状态通常是 0。当您在循环中加入 if(j0) 的复杂逻辑时工具不仅要处理上述的 MUX 逻辑还要处理静态变量的复位逻辑。这导致生成的 RTL 代码极其复杂。Vivado 2018.3 版本在处理这种“带条件复位的复杂状态机”时可能生成了某种边界条件的 RTL 代码导致仿真器编译失败。2.当移除 static 后win_buff 变成了一个局部变量。在 RTL 硬件实现中局部变量通常没有全局复位需求。它只是一个随算法逻辑状态变化的寄存器组。移除 static 后HLS 不再生成复杂的初始化/复位电路逻辑负载减轻。虽然移位逻辑依然因为 if-else 变得复杂不如纯移位高效但由于去掉了复位逻辑的“负赘”仿真器得以勉强完成编译并运行。3.失败原因if(j0) 的分支逻辑破坏了移位寄存器推断生成了巨大的 MUX 逻辑导致 RTL 综合或仿真引擎崩溃。4.移除 static 成功的原因移除静态属性去掉了复位逻辑的负担使工具勉强完成了编译但这只是“治标不治本”硬件效率依然很低。5.最佳实践保持正确代码的写法。不要在流水线循环内部对移位寄存器做复杂的条件初始化利用输出延迟j delay来自然过滤无效数据。