You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 15:34:55