从系统效率和功能可复性方面来讲,当要使得协处理器能够处理更多的应用情景时,应当将目标事物,拆分成一系列更小的重复通用的事物处理过程,在上层软件中再进行事物处理的组装。而当要使得协处理器以系统效率为主,比如低功耗,则需将系统功能整体设计为一个功能单一的模块,做为专用处理器。
本文叙述一个简单的协处理器设计过程,用以加深对RoCC接口的理解。
RoCC加速器模块是由LazyRoCC类继承而来,该模块包含一个由LazyRoCCModuleImp继承而来的实例。
依葫芦画瓢,我们先设计一个加速器模块的外壳,用以可以被Rocket核调用。
class ArraySumCoP(opcodes: OpcodeSet)(implicit p: Parameters) extends LazyRoCC(opcodes) {
override lazy val module = new ArraySumCoPImp(this)
}
class ArraySumCoPImp(outer: ArraySumCoP)(implicit p: Parameters) extends LazyRoCCModuleImp(outer)
with HasCoreParameters {
val cmd = Queue(io.cmd)
...
...
...
}
由于LazyRoCCModuleImp中已经包含了一个RoCCIO的接口,我们可以在实现中直接使用此接口。
RoCCIO接口由多组不同的Wire和bundle组成,具体信息参考上一篇文章:RoCC接口介绍
其中,cmd包含了Custom指令调用时,加速器接收到的内容,参数如下:
- cmd.inst,为32位指令内容,由以下组成:cmd.inst.[opcode, rd, rs1, rs2, funct, xd, xs1, xs2
- cmd.rs1,为源寄存器1内容
- cmd.rs2, 为源寄存器2内容
此外,LazyRoCC
类包含了两个TLOutputNode
实例: atlNode
和tlNode
,分别通过Tilelink总线的方式连接到L1缓存,和L2缓存
mem实例用于直接访问L1 Cache缓存,ptw直接访问页表,busy信号指明加速器是否正在处理指令以及一个中断信号。
本次,我们使用mem接口来实现对内存数据的访问和存储。