Rocket Chip:页表遍历(PTW)触发访问异常求助
RoCC加速器集成RocketChip/Chipyard时PTW访问异常问题
我正尝试将RoCC加速器集成到RocketChip/Chipyard中,该加速器需将虚拟地址转换为物理地址,读取内存数据后启动AES黑盒加速器。参考RocketChip中的TranslatorExample示例,但PTW请求触发了访问异常(ptw.resp.bits.ae_ptw被置位)。以下是我的RoCC代码、配置文件及测试用C代码,请问遗漏了什么?
RoCC代码
class AESAcceleratorModule(outer: MyAESAccelerator)(implicit p: Parameters) extends LazyRoCCModuleImp(outer) with HasCoreParameters { val busy = RegInit(Bool(false)) val req_rd = Reg(Bits(width = 5)) val funct = io.cmd.bits.inst.funct val loadKey = funct === UInt(0) val loadPlain = funct === UInt(1) // Memory Stuff val pte = Reg(new PTE) val input_addr = Reg(UInt(coreMaxAddrBits.W)) val input_offset = input_addr(pgIdxBits - 1, 0) val input_vpn = input_addr(coreMaxAddrBits - 1, pgIdxBits) val input = Reg(UInt(64)) // State Handling object CtrlState extends ChiselEnum { val sIdle, sLoadKey, sPTWalk, sPTResp, sResp = Value } val cstate = RegInit(CtrlState.sIdle) // Default Signal Assign: io.cmd.ready := (cstate === CtrlState.sIdle) io.busy := (cstate =/= CtrlState.sIdle) io.resp.valid := (cstate === CtrlState.sResp || cstate === CtrlState.sLoadKey) io.resp.bits.rd := req_rd io.resp.bits.data := 1.U // Translate Address when(io.cmd.fire && loadPlain){ input_addr := io.cmd.bits.rs1 printf("Input Address: %x\n", io.cmd.bits.rs1) cstate := CtrlState.sPTWalk } private val ptw = io.ptw(0) ptw.req.valid := (cstate === CtrlState.sPTWalk) ptw.req.bits.valid := true.B ptw.req.bits.bits.addr := input_vpn when (ptw.req.fire()) { cstate := CtrlState.sPTResp } when (cstate === CtrlState.sPTResp && ptw.resp.valid) { printf("Got PT Response:\n") pte := ptw.resp.bits.pte cstate := CtrlState.sResp when(ptw.resp.bits.ae_ptw){ printf("Access Exception") // <-- This happens } when(ptw.resp.bits.pf){ printf("Page Fault") } } // Data is 0xFFFF...FF - presumably due to the access exception io.resp.bits.data := Mux(pte.leaf(), Cat(pte.ppn, input_offset), -1.S(xLen.W).asUInt) when (cstate === CtrlState.sResp && io.resp.fire){ input := Mux(pte.leaf(), Cat(pte.ppn, input_offset), -1.S(xLen.W).asUInt) cstate := CtrlState.sIdle } // Be busy when have pending memory requests or committed possibility of pending requests io.interrupt := Bool(false) // Set this true to trigger an interrupt on the processor (please refer to supervisor documentation) io.mem.req.valid := Bool(false) }
配置文件
class MyAESAcceleratorConfig extends Config( new WithMyAESAccelerator ++ new RocketConfig) class WithMyAESAccelerator extends Config ((site, here, up) => { case BuildRoCC => up(BuildRoCC) ++ Seq( (p: Parameters) => { val aes = LazyModule.apply(new MyAESAccelerator(OpcodeSet.custom2)(p)) aes } ) })
测试用C代码
#include <stdio.h> #include "../../tests/rocc.h" int main(void) { uint64_t result = 0; uint64_t myint = 0xAAAAAAAAAAAAAAAA; printf("%lx\n", &myint); asm volatile("fence"); ROCC_INSTRUCTION_DSS(2, result, &myint, 0, 1); printf("The result of func1 was %lx\n", result); return 0; }
问题分析与修复建议
1. PTW请求缺失关键权限/命令字段
当前PTW请求仅设置了addr,缺少访问权限、操作类型等必要字段,导致PTW模块判定请求权限不足,触发访问异常。参考TranslatorExample的实现,需补充以下设置:
ptw.req.bits.bits.cmd := M_XRD // 标记为读操作(匹配读取内存数据的需求) ptw.req.bits.bits.perm := io.cmd.bits.inst.xd || io.cmd.bits.inst.xs // 继承原RoCC指令的特权权限 ptw.req.bits.bits.size := log2Ceil(8).U // 64位数据对应的size值(log2(8)=3)
2. VPN提取逻辑存在位宽错误风险
直接用input_addr(coreMaxAddrBits - 1, pgIdxBits)提取VPN,可能因coreMaxAddrBits与实际虚拟地址位宽不匹配(如RV64的Sv39/Sv48模式下虚拟地址为39/48位而非64位)导致错误。建议改用移位操作更可靠:
val input_vpn = input_addr >> pgIdxBits
3. 确认RoCC的特权访问配置
若测试代码运行在用户态,需确保RoCC被允许发起用户态PTW请求。可检查配置是否开启相关权限,或切换到特权态(如S态)测试,避免用户态权限不足的问题。
4. 移除PTW请求的冗余valid赋值
你设置了ptw.req.bits.valid := true.B,但该字段是PTW请求的内部有效位,通常由ptw.req.valid控制即可,建议移除该冗余赋值。
修改后重新编译测试,即可解决ae_ptw置位的问题。
内容的提问来源于stack exchange,提问作者Jaypthomer
相关产品推荐
相关产品推荐

