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

Why traps Rocket Chip on FPGA after code execution in DRAM

我尝试在 Nexys4 DDR 板上安装一个 Rocket Chip 版本 运行。到目前为止,我设法生成了 verilog,综合了设计并附加了一个 jtag 探针 (segger jlink)。可以通过 openocd 和 gdb 访问寄存器和内存。加载一小段 asm 后,核心开始执行,但在第一个执行指令后直接跳转到 0x0000000。我假设它会陷入陷阱,并且由于陷阱向量未初始化,核心最终为 0。有人知道如何解决这个问题吗?

核的模拟在verilator和vcs上都有效。在这两种情况下,内核都会毫无怨言地执行三个 asm 指令。

测试的asm代码为:

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

链接到这个脚本:

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

对象转储:

Disassembly of section .text:

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

最近 运行 遇到与 DDR4、GDB 和 SiFive RISC 芯片类似的问题。将代码加载到 DDR4 并尝试从复位向量步进后,RISCV 会立即跳转到 0x00000000。在使用 Xilinx ILA 进行调试后,我们发现虽然我们使用 GDB 对 DDR4 内存 space 进行编程,但 RISCV 会在内部缓存一些代码,并且只是偶尔将一些代码推送到 DDR4。从 RISCV 的角度来看,这被认为是可以的,因为当您执行步骤时,它将决定使用缓存(如果可用),否则它将从 DDR4 中检索代码。但是假设您的 CPU 拉动了几次 DDR 访问,因为它需要大量代码来提高效率。如果您的程序真的很小,那么大块代码中的一些可能是空的 space,将不会被编程,因此 ECC 计算不正确。

跳转到0x00000000后查看机器原因寄存器。看是不是提示0x2,非法指令。在我的例子中,我看到这个是因为总线观察到 "bus error",这是由 ECC 故障引起的,对半编程的 DDR 突发。

解决此问题的一种方法可能是在您的 ELF 末尾添加一堆额外的零,这样大小将强制缓存刷新到内存中。一旦对 DDR 进行了真正的编程,并且 ECC 正确无误,您就不会再看到无效指令了。让我知道这是否适合您。