2

我尝试在 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>
4

1 回答 1

1

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

跳转到 0x00000000 后检查机器原因寄存器。看是否表示0x2,非法指令。在我的例子中,我看到这是因为总线观察到“总线错误”,这是由 ECC 故障对半编程 DDR 突发造成的。

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

于 2019-08-09T06:44:08.253 回答