“Rocket Chip – 访问页表步骤中的异常”

huangapple go评论93阅读模式
英文:

Rocket Chip - Access Exception on Page Table Walk

问题

I'll provide translations for the code you've shared. Here's the translated code:

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)

    
    // 内存相关
    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))

    // 状态处理
    object CtrlState extends ChiselEnum {
        val sIdle, sLoadKey, sPTWalk, sPTResp, sResp = Value
    }
    val cstate = RegInit(CtrlState.sIdle)

    // 默认信号分配:
    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

    // 翻译地址
    when(io.cmd.fire && loadPlain){
        input_addr := io.cmd.bits.rs1
        printf("输入地址:%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("得到PT响应:\n")
        pte := ptw.resp.bits.pte
        cstate := CtrlState.sResp
        when(ptw.resp.bits.ae_ptw){
            printf("访问异常") // <-- 这会发生
        }
        when(ptw.resp.bits.pf){
            printf("页错误")
        }
    }

    // 数据为0xFFFF...FF - 可能是由于访问异常引起的
    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 
    }
    
    // 当有待处理的内存请求或可能有待处理请求的情况下忙碌
    io.interrupt := Bool(false)
    
    // 将此设置为true以触发处理器上的中断(请参考监控程序文档)
    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("func1的结果为 %lx\n", result);

    return 0;
}

请注意,翻译可能不是逐字逐句的,但应能反映源代码的主要功能和逻辑。

英文:

I am trying to integrate a RoCC accelerator with RocketChip / Chipyard. Given a virtual address, the accelerator should translate it to a physical address, read some data from memory and then start a black box accelerator (e.g. AES).
I looked at some examples and (so far) mostly followed the TranslatorExample included in RocketChip. However, the PTW request throws an access exception (ptw.resp.bits.ae_ptw is set). What am I missing?

This is my RoCC code:

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 &amp;&amp; loadPlain){
input_addr := io.cmd.bits.rs1
printf(&quot;Input Address: %x\n&quot;, 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 &amp;&amp; ptw.resp.valid) {
printf(&quot;Got PT Response:\n&quot;)
pte := ptw.resp.bits.pte
cstate := CtrlState.sResp
when(ptw.resp.bits.ae_ptw){
printf(&quot;Access Exception&quot;) // &lt;-- This happens
}
when(ptw.resp.bits.pf){
printf(&quot;Page Fault&quot;)
}
}
// 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 &amp;&amp; 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)
}

And the config file:

class MyAESAcceleratorConfig extends Config(
new WithMyAESAccelerator ++
new RocketConfig)
class WithMyAESAccelerator extends Config ((site, here, up) =&gt; {
case BuildRoCC =&gt; up(BuildRoCC) ++ Seq(
(p: Parameters) =&gt; {
val aes = LazyModule.apply(new MyAESAccelerator(OpcodeSet.custom2)(p))
aes
}
)
})

This is the C code I am executing which does not return the desired result:

#include &lt;stdio.h&gt;
#include &quot;../../tests/rocc.h&quot;
int main(void)
{
uint64_t result = 0;
uint64_t myint =   0xAAAAAAAAAAAAAAAA;
printf(&quot;%lx\n&quot;, &amp;myint);
asm volatile(&quot;fence&quot;);
ROCC_INSTRUCTION_DSS(2, result, &amp;myint, 0, 1);
printf(&quot;The result of func1 was %lx\n&quot;, result);
return 0;
}

答案1

得分: 1

如果您还没有弄清楚,我假设您正在运行裸机C测试。在裸机VM中不使用。可以通过检查ptbr.mode信号来找出这一点(请参阅RISC-V特权规范第4节)。
如果您想测试页表控制器(PTW),您可以使用spike或VCS/verilator与代理内核一起运行。

英文:

In case you haven't figured this out, I assume you are running baremetal C tests. In baremetal VM is not used. This can be found out by checking the ptbr.mode signal (see RISC-V privileged spec section 4).
If you want to test PTW, you can run spike or VCS/verilator with proxy kernel.

huangapple
  • 本文由 发表于 2023年5月17日 16:44:27
  • 转载请务必保留本文链接:https://go.coder-hub.com/76270148.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定