下面是对translator模块的具体实现进行说明。
2、Translator
类TranslatorExample,需要输入opcodes参数,里面使用new创建TranslatorExampleModuleImp的对象,且输入额外参数nPTWPorts,值为1。
class TranslatorExample(opcodes: OpcodeSet)(implicit p: Parameters) extends LazyRoCC(opcodes, nPTWPorts = 1) {
override lazy val module = new TranslatorExampleModuleImp(this)
}
TranslatorExampleModuleImp类中混入LazyRoCCModuleImp和HasCoreParameters。
- 声明req_addr的值为寄存器,宽度为coreMaxAddrBits,这里coreMaxAddrBits=32。
- 声明req_rd的值为寄存器,位宽与io.resp.bits.rd的位宽一样。
- 声明req_offset的值为req_addr(11,0),取req_addr的低12位,pgIdxBits在tile/BaseTile.scala中定义,def pgIdxBits: Int = 12。
- 声明req_vpn为req_addr(coreMaxAddrBits - 1, pgIdxBits)即req_addr(31, 12)。
这里将req_addr分为了req_offset和req_vpn,一个是偏移值,一个是虚拟页面编号值。由此可知一个虚拟页面有64B数据。 - 声明pte的值为寄存器,类型为PTE类,类PTE是一个多信号的组合,类PTE可以查看rocket/PTW.scala。
这里 Enum() 生成四个Bits类型的字面常量,分别为s_idle、s_ptw_req、s_ptw_resp和s_resp
,作为有限状态机的状态,同时声明state为寄存器,用于存储状态机的状态值,初始值为s_idle。
当state为s_idle时,io.cmd.ready为1,也就是Translator模块处于空闲状态。 - 当io.cmd.fire()为1时,也就是io.cmd.ready为1 && io.cmd.valid为1,也就是Translator模块处于空闲,且core那边有有效指令传输过来,那就将io.cmd.bits.inst.rd赋给req_rd,将 io.cmd.bits.rs1赋给req_addr,state更新状态为s_resp,上述操作均为时序操作。
- 定义私有成员ptw,仅在此类中可见。ptw的值为io.ptw端口中的第0号ptw信号组,存在多组ptw端口,部分用于pmp的用途,在TranslatorExampleModuleImp类中,后面的ptw信号都是这个私有信号。
- 当ptw.req.ready为1和ptw.req.valid为1时,状态机转变为s_ptw_resp。
- 当状态机为s_ptw_resp ,且ptw.resp.valid为1时,将ptw端口返回的pte信号组赋给类中的pte寄存器。同时将状态改为s_resp。
- 当io.resp.ready为1和io.resp.valid为1时,状态机跳转回s_idle态。
- 当状态机为s_ptw_req时,ptw.req.valid置1。
- ptw.req.bits.valid永远为1。
- 将req_vpn的值赋给ptw.req.bits.bits.addr。
- 当状态机为s_resp时,io.resp.valid置1。
- 将req_rd的值赋给io.resp.bits.rd。
- io.resp.bits.data的值是一个mux输出,选择信号为pt

最低0.47元/天 解锁文章
2030

被折叠的 条评论
为什么被折叠?



