这节的主要内容是教大家如何自由配置一个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)
}
第二个看的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
)
欲知后事如何,请听下回分解。
有兴趣的朋友可以在评论中留下你们想改的功能,我看能不能改出来,谢谢大家。