Loading

Rocket——BootRom

Bootrom是嵌入处理器芯片内的一小块掩模ROM,包含处理器在上电或复位时执行的第一个代码。bootrom结构如下所示(图自10-02 晶片內建Boot Rom記憶體映設圖介紹_哔哩哔哩_bilibili):

 rocket中的code bootrom.s是rocket-chip/bootrom.S at master · chipsalliance/rocket-chip (github.com),rocket-chip生成的rom是固化代码的,它是从/rocket-chip/bootrom目录中读取bootrom.img作为rom的原始代码,然后在chisel & firrtl生成代码时,将bootrom.img的内容写入到bootrom模块中。bootrom.s注释如下:

//定义dram起始地址是0x8000_0000
#define DRAM_BASE 0x80000000

.section .text.start, "ax", @progbits
.globl _start
//_start地址是0x10000
_start:
  csrwi 0x7c1, 0 // disable chicken bits
  li s0, DRAM_BASE
  csrr a0, mhartid
  la a1, _dtb
//跳转到s0的地址,也就是8000_0000
  jr s0

//_hang的地址是10040,其会等待debug模块发来的一个中断
.section .text.hang, "ax", @progbits
.globl _hang
_hang:
  csrwi 0x7c1, 0 // disable chicken bits
  csrr a0, mhartid
  la a1, _dtb
  csrwi mie, 0
1:
  wfi
  j 1b

.section .rodata.dtb, "a", @progbits
.globl _dtb
.align 5, 0
_dtb:
.ascii "DTB goes here"

可见,如果我们通过系统函数将自己的hex写入0x8000_0000开头的sram中,并让cpu执行,需要修改bootrom的resetvector,让其从复位后的0x10000地址开始执行,即可顺利跳转到0x8000_0000地址处。

 

1,修改src/main/scala/devices/tilelink/BootROM.scala中的case class BootROMParams,让hang: BigInt=0x10000

FIX (improve-boot-1): change reset vector address by T-K-233 · Pull Request #3328 · chipsalliance/rocket-chip (github.com)

但经过测试发现系统并没有跳转到0x8000_0000执行,为此我们需要详细分析一下soc上电后执行rom代码的行为。首先看看rom的接口:

 rom和cpu交互采用tilelink总线接口,关于tilelink部分的基础信息参加论文阅读:Diplomatic Design Patterns: A TileLink Case Study - Haowen_Zhao - 博客园 (cnblogs.com)

 其ROM的TL接口信号如下:

 a接口是cpu->rom的,d接口是rom->cpu的,两个接口都是单向的,a接口是请求数据的,d接口是返回数据的。

 而经过检查发现bootrom的载入是没问题的。那么我们看看cpu读取到rom数据后的行为。

 经过debug,发现是rocket-chip/bootrom/bootrom.img官方镜像的问题,经过修改重新生成rtl,成功从0x8000_0000启动:

 

posted @ 2023-04-25 16:56  Haowen_Zhao  阅读(368)  评论(0编辑  收藏  举报