简体   繁体   English

为什么在DRAM中执行代码后将Rocket Chip捕获在FPGA上

[英]Why traps Rocket Chip on FPGA after code execution in DRAM

I try to get a version of Rocket Chip on a Nexys4 DDR board up and running. 我尝试在Nexys4 DDR板上安装并运行一个Rocket Chip版本。 So far I managed to generate the verilog, synthesize the design and attach a jtag probe (segger jlink). 到目前为止,我设法生成了verilog,综合了设计并附加了一个jtag探针(segger jlink)。 It is possible to access registers and memory via openocd and gdb. 可以通过openocd和gdb访问寄存器和内存。 After loading a small snippet of asm the core starts executing but jumps after the first executed instruction directly to 0x0000000. 加载一小段asm代码后,内核开始执行,但在第一个执行的指令后直接跳转到0x0000000。 I assume it traps and since the trap vector is not initialized the core ends up at 0. Does anybody know how to fix this? 我认为它是陷阱,并且由于陷阱矢量未初始化,因此内核最终为0。有人知道如何解决此问题吗?

The simulation of the core works both with verilator and vcs. 内核的仿真可与verilator和vcs一起使用。 In both cases the core executes the three asm instructions without complains. 在这两种情况下,内核都会执行三个asm指令而不会产生抱怨。

The tested asm code is: 经过测试的asm代码为:

.section .text                                                                  
.global _start                                                                  
_start:                                                                         
    add x0,x0,x0                                                                
    add x0,x0,x0                                                                                                                             
    j _start

linked with the this script: 与此脚本链接:

SECTIONS
{
    . = 0x80000000;
    .text : { *(.text) }
}

Object dump: 对象转储:

Disassembly of section .text:

0000000080000000 <_start>:
    80000000:   00000033                add     zero,zero,zero
    80000004:   00000033                add     zero,zero,zero
    80000008:   ff9ff06f                j       80000000 <_start>

Recently ran into a similar issue with DDR4, GDB and a SiFive RISC chip. 最近,DDR4,GDB和SiFive RISC芯片也遇到了类似的问题。 After loading code onto the DDR4, and attempting to step from the reset vector, the RISCV would immediately jump to 0x00000000. 将代码加载到DDR4上并尝试从复位向量开始执行之后,RISCV将立即跳至0x00000000。 After debuging with a Xilinx ILA, we found that although we were programming the DDR4 memory space with GDB, the RISCV was caching some of the code internally, and only occasionally pushing some to the DDR4. 在使用Xilinx ILA进行调试之后,我们发现尽管我们使用GDB对DDR4存储器空间进行了编程,但是RISCV在内部缓存了一些代码,并且偶尔将一些代码推送到DDR4。 From the RISCV point of view, this is thought to be okay because, when you step and it will decide to use cache if available, otherwise it would retrieve code from the DDR4. 从RISCV的角度来看,这被认为是可以的,因为当您执行步骤时,它将决定使用高速缓存(如果可用),否则它将从DDR4中检索代码。 But lets say your CPU pulls several bursts of DDR accesses because it wants a lot of code for efficency. 但是可以说,您的CPU拉动了几次DDR访问突发,因为它需要大量代码来提高效率。 Some of that large chunk of code, which could be empty space if your program is really small, will not have been programmed and thus the ECC is not calculated correctly. 那些很大的代码块中的一些(如果您的程序真的很小,可能是空白)可能没有被编程,因此ECC计算不正确。

Check the machine cause register after jumping to 0x00000000. 跳转到0x00000000后,检查机器原因寄存器。 See if it indicates 0x2, illegal instruction. 看看它是否指示0x2,非法指令。 In my case, I saw this because the bus observed a "bus error", which was induced by an ECC fault do to a half programmed DDR burst. 就我而言,我之所以会这样,是因为总线观察到了“总线错误”,该错误是由ECC故障导致的,编程的DDR突发突发次数为一半。

One way to work around this might be to pad your ELF with a bunch of extra zeros at the end such that the size will force the cache to flush to the memory. 解决此问题的一种方法可能是在ELF末尾添加一堆额外的零,以使该大小将强制高速缓存刷新到内存。 Once the DDR is really programmed, and the ECC's are correct, you shouldn't see the invalid instruction anymore. 一旦对DDR进行了真正的编程,并且ECC正确,您就不再应该看到无效的指令。 Let me know if that works for you or not. 让我知道这是否对您有用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM