如何配置一个自定义的rocket-chip?

如何配置一个自定义的rocket-chip?

这节的主要内容是教大家如何自由配置一个rocket-chip。

以下是我对rocket-chip修改后实现的特殊功能(部分我会以例子的形式进行说明):
1、 将reset_vector信号引到顶层,可以根据该信号使rocket-chip从不同地址启动。
2、 在rocket-chip的顶层引出一套采用Tilelink的SRAM,这套SRAM按物理地址访问。
3、 修改各总线(mem/MMIO)的物理访问地址。
4、 将各总线(mem/MMIO)的AXI4协议改为AHB协议。
5、 将local interrupt的信号引到rocket-chip的顶层,使除了PLIC外,还能使用local interrupt。
6、 修改ROCC的功能,扩展custom0、custom1、custom2和custom3的功能。
7、 加入DCache enable的CSR寄存器,并实现相应功能,使DCache的功能变为可选。

现在先对rocket-chip的Scala代码进行简单的介绍。

cd /rocket-chip/src/main/scala
ls
amba    devices     groundtest  jtag       rocket     system  tilelink  util
config  diplomacy   interrupts  regmapper  subsystem  tile    unittest

我决定以从顶到底的方式解释rocket-chip的Scala代码,此外我不会每个Scala文件都一一说明,某些测试的Scala文件我会跳过的。
首先说明的是/rocket-chip/src/main/scala/system目录:

Configs.scala   ExampleRocketSystem.scala 
Generator.scala RocketTestSuite.scala  TestHarness.scala

Generator.scala & RocketTestSuite.scala 这两个文件是测试相关的,所以我不做说明。

第一个看的Scala文件是:TestHarness.scala
带//注释的就是解释。

class TestHarness()(implicit p: Parameters) extends Module {
  		//注释:声明一个io Bundle,里面包含一个输出、Bool类型的常量success。
  val io = new Bundle {
    val success = Bool(OUTPUT)
  }

  		//注释:生成一个module,利用dut来表示这个module,这个module是调用ExampleRocketSystem的。
  		//注释:在/system/ExampleRocketSystem.scala中定义。
  val dut = Module(LazyModule(new ExampleRocketSystem).module)
  		//注释:dut的复位是外部reset与dut debug模块的ndreset信号的或。
  dut.reset := reset | dut.debug.ndreset

  		//注释:调用dut的dontTouchPorts的方法,这个是使某些信号不被接触,我暂时也不十分理解,
  		//不过我们后面不对这个进行修改,所以直接用就好。
  		//注释:在/util/Annotations.scala中定义。
  dut.dontTouchPorts()

  		//注释:这是我修改后的方法,主要是将dut和AHB协议的仿真SRAM对接。
  		//注释:在/subsystem/Ports.scala中定义。
  dut.connectSimAHBMem()

  		//注释:这个是将dut的中断信号全部接0。
  		//注释:在/subsystem/InterruptBus.scala中定义。
  //dut.tieOffInterrupts()

  		//注释:这些是原有的AXI接口,Mem和MMIO,因为我改了使用AHB协议,所以屏蔽。
  		//注释:在/subsystem/Ports.scala中定义。
  //dut.connectSimAXIMem()
  //dut.connectSimAXIMMIO()

  		//注释:这是frontend的接口,这个接口CPU是作为slave的,外部设备是作为master的,
  		//功能类似于SiFive的frontport,下面两个都是frontend的接口,只是一个采用AXI4协议,一个采用Tilelink协议。
  		//注释:在/subsystem/Ports.scala中定义。
  //dut.l2_frontend_bus_axi4.foreach(_.tieoff)
  //dut.l2_frontend_bus_tl.foreach(_.tieoff)

 	 	//注释:这个也是frontend的接口,只是我修改后,采用了AHB协议。
  		//注释:在/subsystem/Ports.scala中定义 。
  dut.l2_frontend_bus_ahb.foreach(_.tieoff)

  		//注释:主要作用是将SimJTAG.v与dut相连,并输出io.success来确定仿真是否成功。
  		//注释:SimJTAG.v在/rocket-chip/vsim/generated-src/xxx目录中可以找到。
  		//注释:在/devices/debug/Periphery.scala中定义。
  dut.connectDebug(clock, reset, io.success)
}

下图是 TestHarness.scala 生成的连接图。
在这里插入图片描述

第二个看的Scala文件是:ExampleRocketSystem.scala
可以知道 TestHarness.scala 就是testbench,而 ExampleRocketSystem.scala 生成的才是我们关注的SOC, ExampleRocketSystem.scala 包括Core以外的其他外设&总线。

/** Example Top with periphery devices and ports, and a Rocket subsystem */
		//注释:类似的,ExampleRocketSystem是在RocketSubsystem的基础上进行扩展的。
	 	//注释:RocketSubsystem是在/subsystem/RocketSubsystem.scala中定义的类。
class ExampleRocketSystem(implicit p: Parameters) extends RocketSubsystem
		//注释:我修改后的SRAM,总线接口是Tilelink协议。
		//注释:在/tilelink/SRAM.scala中定义。
	with HasPeripheryRAM
		//注释:将Ext-Interrupts(PLIC的中断源)引入ibus中同步,即异步信号同步化。
		//注释:在/subsystem/InterruptBus.scala中定义。
	with HasAsyncExtInterrupts
		//注释:将Local-Interrupts引入ibus中同步,即异步信号同步化,这是我修改的。
		//注释:在/subsystem/InterruptBus.scala中定义。
	with HasAsyncLocalInterrupts
		//注释:调用AHB协议的memory_port,这个也是我修改的。
		//注释:在/subsystem/Ports.scala中定义。
	with CanHaveMasterAHBMemPort
		//注释:调用AHB协议的frontend_bus,这个也是我修改的。
		//注释:在/subsystem/Ports.scala中定义。
	with CanHaveSlaveAHBPort
		//注释:调用Tilelink协议的frontend_bus。
		//注释:在/subsystem/Ports.scala中定义。
	//with CanHaveSlaveTLPort
		//注释:调用AXI4协议的memory_port。
		//注释:在/subsystem/Ports.scala中定义。
	//with CanHaveMasterAXI4MemPort
		//注释:调用AXI4协议的mmio_port。
		//注释:在/subsystem/Ports.scala中定义。
	//with CanHaveMasterAXI4MMIOPort
		//注释:调用AXI4协议的frontend_bus。
		//注释:在/subsystem/Ports.scala中定义。
	//with CanHaveSlaveAXI4Port
		//注释:调用BootROM模块。
		//注释:在/devices/tilelink/BootROM.scala中定义。
	//with HasPeripheryBootROM
		//注释:sbus会传递Tilelink的某些Error。
		//注释:在/devices/tilelink/Error.scala中定义。
    with HasSystemErrorSlave 
{
  override lazy val module = new ExampleRocketSystemModuleImp(this)
}

		// ExampleRocketSystemModuleImp是具体的端口连接模块。
		// RocketSubsystemModuleImp是在/subsystem/RocketSubsystem.scala中定义的类
class ExampleRocketSystemModuleImp[+L <: ExampleRocketSystem](_outer: L) extends RocketSubsystemModuleImp(_outer)
		//注释:用于连接CLINT timer的时钟输入,可以直接将rtc_clk引到顶层中。
		//注释:在/subsystem/RTC.scala中定义。
	with HasRTCModuleImp
		//注释:将顶层的中断源(Ext-Interrupts)信号接到ExtInterruptsModule中。
		//注释:在/subsystem/InterruptBus.scala中定义。
	with HasExtInterruptsModuleImp
		//注释:将顶层的中断源(Local-Interruptss)信号接到LocalInterruptsModule中。
		//注释:在/subsystem/InterruptBus.scala中定义。
	with HasLocalInterruptsModuleImp
		//注释:将AHB协议的SRAM和DUT(ExampleRocketSystem)的memory_port总线(AHB协议)相连。
		//注释:在/subsystem/Ports.scala中定义。
	with CanHaveMasterAHBMemPortModuleImp
		//注释:将顶层的frontend_bus信号(AHB协议)接到SlaveAHBPortModule中。
		//注释:在/subsystem/Ports.scala中定义。
    with CanHaveSlaveAHBPortModuleImp
    	//with CanHaveSlaveTLPortModuleImp
		//注释:将AXI4协议的SRAM和DUT(ExampleRocketSystem)的memory_port总线(AXI4协议)相连。
		//注释:在/subsystem/Ports.scala中定义。
	//with CanHaveMasterAXI4MemPortModuleImp
		//注释:将AXI4协议的SRAM和DUT(ExampleRocketSystem)的mmio_port总线(AXI4协议)相连。
		//注释:在/subsystem/Ports.scala中定义。
	//with CanHaveMasterAXI4MMIOPortModuleImp
		//注释:将顶层的frontend_bus信号(AXI4协议)接到SlaveAXI4PortModule中。
		//注释:在/subsystem/Ports.scala中定义。
	//with CanHaveSlaveAXI4PortModuleImp
		//注释:将global_reset_vector接着BootROM的地址上,固定rocket-chip从BootROM开始启动。
		//注释:在/devices/tilelink/BootROM.scala中定义。
    //with HasPeripheryBootROMModuleImp
    with DontTouch

第三个看的Scala文件是:Configs.scala
TestHarness.scala 就是testbench,而 ExampleRocketSystem.scala 就是SOC的层次,包括Core以外的其他外设&总线,Configs.scala 就是核心Core的配置。Configs.scala 的配置比较多,我挑几个来说明。

		//注释:Core的一些基础配置,在/scala/subsystem/Configs.scala中有各个配置的详细说明。
class BaseConfig extends Config(
		//注释:配置Mem_Port的起始地址、总线宽度、多拍数据传输的字节数。
  new WithDefaultMemPort() ++
		//注释:配置MMIO_Port的起始地址、总线宽度、多拍数据传输的字节数。
  //new WithDefaultMMIOPort() ++
		//注释:配置Slave_Port(frontend_bus)的多拍数据传输的字节数。
  new WithDefaultSlavePort() ++
		//注释:配置DTS的基础时间。
  new WithTimebase(BigInt(1000000)) ++ // 1 MHz
		//注释:配置DTS的model、compat。
  new WithDTS("freechips,rocketchip-unknown", Nil) ++
		//注释:配置Core的外部中断源数量。
  new WithNExtTopInterrupts(32) ++
		//注释:配置Core基础系统的内容,如位宽、虚拟内容的类型、各类型总线的特性、BootROM的内容、Debug的参数、CLINT的参数等。
  new BaseSubsystemConfig()
)

class DefaultSmallConfig extends Config(
		//注释:生成的Core带有BTB分支预测功能。
  new WithDefaultBtb ++
  		//注释:生成的Core带ROCC的接口,用于定制指令的扩展。
new WithRoccExample ++
		//注释:指定Core是32位系统,且指定浮点数据的位宽和乘除法的类型。
  new WithRV32 ++
		//注释:生成的Core带有DTM模块,兼容JTAG调试功能。
  new WithJtagDTM ++
		//注释:生成的Core去除Tilelink的Monitor模块。
  new WithoutTLMonitors ++
		//注释:指定Core中cache line的字节数,即32Bytes=8Words。
  new WithCacheBlockBytes(32) ++
		//注释:生成一个SmallCore,SmallCore配置中可以指定ICache & DCache的路数,深度等信息,有些配置会因为上面已经配置了而被覆盖。
  new WithNSmallCores(1) ++ 
		//注释:Core的一些基础配置,如总线、DTS & 中断等。
  new BaseConfig
)

欲知后事如何,请听下回分解。

有兴趣的朋友可以在评论中留下你们想改的功能,我看能不能改出来,谢谢大家。

评论 31
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值