查看: 1790|回复: 0
收起左侧

RISC-V:控制与状态寄存器(CSR)

[复制链接]

  离线 

  • TA的每日心情
    奋斗
    2021-3-3 12:32
  • 签到天数: 10 天

    [LV.3]

    发表于 2020-8-23 20:50:20 | 显示全部楼层 |阅读模式

    有人预言,RISC-V或将是继Intel和Arm之后的第三大主流处理器体系。欢迎访问全球首家只专注于RISC-V单片机行业应用的中文网站

    您需要 登录 才可以下载或查看,没有帐号?立即注册

    x
    本帖最后由 皋陶 于 2020-8-26 15:19 编辑

    RISC-V:控制与状态寄存器(CSR)
    芯片示意图

    管脚信息
    名称方向类型作用
    interruptsinputCoreInterrupts输入:相关的中断信息
    hartidinputUInt输入:硬件线程id
    rwexchange结构体输入:指令 输出:操作的寄存器结果
    decodeexchangeVec(new CSRDecodeIO)输入:指令 输出:异常控制线
    csr_stalloutputBool输出:csr暂停(stall)
    eretoutputBool是否执行call、break、ret
    singleStepoutputBool输出:单步控制
    statusoutputMStatus输出:mstatus情况
    ptbroutputPTBR输出:翻译和保护寄存器情况
    evecoutputUInt输出:陷入地址
    exceptioninputBool输入:外部异常
    retireinputUInt输入:是否有效
    causeinputUInt输入:中断原因
    pcinputUInt输入:当前pc值
    tvalinputUInt输入:引起异常的值
    timeoutputUInt输出:进程执行周期
    fcsr_rmoutputBits输出:浮点读舍入模式
    fcsr_flagsexchangeValid(Bits)交换:浮点读异常标志
    set_fs_dirtyinputBool输入:指定浮点脏标志
    rocc_interruptinputBool输入:协处理器中断
    interruptoutputBool输出:判断是否发生中断
    interrupt_causeoutputUInt输出:判断发生中断的原因
    bpoutputVec(new BP)输出:断点情况
    pmpoutputVec(new PMP)输出:内存保护情况
    countersexchangeVec(new PerfCounterIO)输入:hpmcounter的inc 输出:hpmevent情况
    csrw_counteroutputUInt输出:使用的counter下标
    instinputVec(UInt)输入:trace命令
    traceoutputVec(new TracedInstruction)输出:trace情况
    customCSRsexchangeVec(new CustomCSRIO)交换:传统csr

    流程说明1.reg_mip寄存器

    (1)reg_mip结构


    1. class MIP(implicit p: Parameters) extends CoreBundle()(p)
    2.     with HasCoreParameters {
    3.   val lip = Vec(coreParams.nLocalInterrupts, Bool())
    4.   val zero2 = Bool()
    5.   val debug = Bool() // keep in sync with CSR.debugIntCause
    6.   val zero1 = Bool()
    7.   val rocc = Bool()
    8.   val meip = Bool()
    9.   val heip = Bool()
    10.   val seip = Bool()
    11.   val ueip = Bool()
    12.   val mtip = Bool()
    13.   val htip = Bool()
    14.   val stip = Bool()
    15.   val utip = Bool()
    16.   val msip = Bool()
    17.   val hsip = Bool()
    18.   val ssip = Bool()
    19.   val usip = Bool()
    20. }

    21. val reg_mip = Reg(new MIP)
    复制代码

    (2) reg_mip赋值


    1. val mip = Wire(init=reg_mip)
    2. mip.lip := (io.interrupts.lip: Seq[Bool])
    3. mip.mtip := io.interrupts.mtip
    4. mip.msip := io.interrupts.msip
    5. mip.meip := io.interrupts.meip
    6. // seip is the OR of reg_mip.seip and the actual line from the PLIC
    7. io.interrupts.seip.foreach { mip.seip := reg_mip.seip || RegNext(_)
    8. mip.rocc := io.rocc_interrupt
    复制代码


    <1> reg_mip寄存器的mtip、msip、meip段,由输入管脚interrupts的对应部分决定
    <2> reg_mip寄存器的rocc段,由输入管脚rocc_interrupt决定
    <3> reg_mip寄存器的seip段,由输入reg_mip.seip || RegNext(io.interrupts.seip)决定,即reg_mip的seip段或延迟一时钟的interrupts.seip管脚决定

    (3)reg_mip赋值情况一


    1. when (decoded_addr(CSRs.mip)) {
    2. // MIP should be modified based on the value in reg_mip, not the value
    3. // in read_mip, since read_mip.seip is the OR of reg_mip.seip and
    4. // io.interrupts.seip.  We don't want the value on the PLIC line to
    5. // inadvertently be OR'd into read_mip.seip.
    6. val new_mip = readModifyWriteCSR(io.rw.cmd, reg_mip.asUInt, io.rw.wdata).asTypeOf(new MIP)
    7. if (usingVM) {
    8. reg_mip.ssip := new_mip.ssip
    9. reg_mip.stip := new_mip.stip
    10. reg_mip.seip := new_mip.seip
    11. }
    复制代码


    <1> 当操作为修改reg_mip寄存器mip段时,修改的reg_mip寄存器ssip、msip、meip段为对应的数据


    (4)reg_mip赋值情况二


    1. when (decoded_addr(CSRs.sip)) {
    2. val new_sip = new MIP().fromBits((read_mip & ~reg_mideleg) | (wdata & reg_mideleg))
    3. reg_mip.ssip := new_sip.ssip
    4. }
    复制代码


    <1> 当操作为修改reg_mip寄存器sip段时,修改的reg_mip寄存器ssip段为对应的数据


    (5)支持的中断,委托的中断


    1. val (supported_interrupts, delegable_interrupts) = {
    2.     val sup = Wire(new MIP)
    3.     sup.usip := false
    4.     sup.ssip := Bool(usingVM)
    5.     sup.hsip := false
    6.     sup.msip := true
    7.     sup.utip := false
    8.     sup.stip := Bool(usingVM)
    9.     sup.htip := false
    10.     sup.mtip := true
    11.     sup.ueip := false
    12.     sup.seip := Bool(usingVM)
    13.     sup.heip := false
    14.     sup.meip := true
    15.     sup.rocc := usingRoCC
    16.     sup.zero1 := false
    17.     sup.debug := false
    18.     sup.zero2 := false
    19.     sup.lip foreach { _ := true }
    20.     val supported_high_interrupts = if (io.interrupts.buserror.nonEmpty) UInt(BigInt(1) << CSR.busErrorIntCause) else 0.U
    21.    
    22.     val del = Wire(init=sup)
    23.     del.msip := false
    24.     del.mtip := false
    25.     del.meip := false
    26.     (sup.asUInt | supported_high_interrupts, del.asUInt)
    27. }        
    复制代码


    (6)中断情况、断点情况、内存保护情况反馈


    1. val pending_interrupts = high_interrupts | (read_mip & reg_mie)
    2. val d_interrupts = io.interrupts.debug << CSR.debugIntCause
    3. val m_interrupts = Mux(reg_mstatus.prv <= PRV.S || reg_mstatus.mie, ~(~pending_interrupts | reg_mideleg), UInt(0))
    4. val s_interrupts = Mux(reg_mstatus.prv < PRV.S || (reg_mstatus.prv === PRV.S && reg_mstatus.sie), pending_interrupts & reg_mideleg, UInt(0))
    5. val (anyInterrupt, whichInterrupt) = chooseInterrupt(Seq(s_interrupts, m_interrupts, d_interrupts))
    6. val interruptMSB = BigInt(1) << (xLen-1)
    7. val interruptCause = UInt(interruptMSB) + whichInterrupt

    8. io.interrupt := (anyInterrupt && !io.singleStep || reg_singleStepped) && !reg_debug
    9. io.interrupt_cause := interruptCause
    10. io.bp := reg_bp take nBreakpoints
    11. io.pmp := reg_pmp.map(PMP(_))
    复制代码


    2.特权模式转换

    (1)复位后mstatus;mpp:中断前级别:机器模式;prv:内存可访问级别:机器模式

    1.   val reset_mstatus = Wire(init=new MStatus().fromBits(0))
    2.   reset_mstatus.mpp := PRV.M
    3.   reset_mstatus.prv := PRV.M
    复制代码


    3.reg_misa寄存器

    1. val isaMaskString =
    2.     (if (usingMulDiv) "M" else "") +
    3.     (if (usingAtomics) "A" else "") +
    4.     (if (fLen >= 32) "F" else "") +
    5.     (if (fLen >= 64) "D" else "") +
    6.     (if (usingCompressed) "C" else "") +
    7.     (if (usingRoCC) "X" else "")
    8.   val isaString = "I" + isaMaskString +
    9.     (if (usingVM) "S" else "") +
    10.     (if (usingUser) "U" else "")
    11.   val isaMax = (BigInt(log2Ceil(xLen) - 4) << (xLen-2)) | isaStringToMask(isaString)
    12.   val reg_misa = Reg(init=UInt(isaMax))
    复制代码
    1. io.status.isa := reg_misa
    复制代码

    4.CSR写或读逻辑

    1. //地址匹配情况
    2. val decoded_addr = read_mapping map { case (k, v) => k -> (io.rw.addr === k) }
    3. //读或者写操作
    4. val wdata = readModifyWriteCSR(io.rw.cmd, io.rw.rdata, io.rw.wdata)
    复制代码

    5.CSR指令

    1.   val system_insn = io.rw.cmd === CSR.I
    2.   val decode_table = Seq(
    3.     SCALL->     List(Y,N,N,N,N),
    4.     SBREAK->    List(N,Y,N,N,N),
    5.     MRET->      List(N,N,Y,N,N),
    6.     WFI->       List(N,N,N,Y,N)) ++ (if (usingDebug) Seq(
    7.     DRET->      List(N,N,Y,N,N)) else Seq()) ++ (if (usingVM) Seq(
    8.     SRET->      List(N,N,Y,N,N),
    9.     SFENCE_VMA->List(N,N,N,N,Y)) else Seq())
    10.   val insn_call::insn_break::insn_ret::insn_wfi::insn_sfence::Nil = DecodeLogic(io.rw.addr << 20, decode_table(0)._2.map(x=>X), decode_table).map(system_insn && _.toBool)
    复制代码

    6.CSR异常

    1. for (io_dec <- io.decode) {
    2.     val is_call::is_break::is_ret::is_wfi::is_sfence::Nil = DecodeLogic(io_dec.csr << 20, decode_table(0)._2.map(x=>X), decode_table).map(_.toBool)
    3.     def decodeAny(m: LinkedHashMap[Int,Bits]): Bool = m.map { case(k: Int, _: Bits) => io_dec.csr === k }.reduce(_||_)
    4.     //allow_wfi:未使用虚拟化||当前机器模式||监督模式tw为0
    5.     val allow_wfi = Bool(!usingVM) || reg_mstatus.prv > PRV.S || !reg_mstatus.tw
    6.     //allow_sfence_vma:未使用虚拟化||当前机器模式||监督模式tvm为0
    7.     val allow_sfence_vma = Bool(!usingVM) || reg_mstatus.prv > PRV.S || !reg_mstatus.tvm
    8.     //allow_sret:未使用虚拟化||当前机器模式||监督模式tsr为0
    9.     val allow_sret = Bool(!usingVM) || reg_mstatus.prv > PRV.S || !reg_mstatus.tsr
    10.     val counter_addr = io_dec.csr(log2Ceil(reg_mcounteren.getWidth)-1, 0)
    11.     //allow_counter:当前监督模式||计数使能寄存器地址使能情况
    12.     val allow_counter = (reg_mstatus.prv > PRV.S || reg_mcounteren(counter_addr)) &&
    13.       (reg_mstatus.prv >= PRV.S || reg_scounteren(counter_addr))
    14.     io_dec.fp_illegal := io.status.fs === 0 || !reg_misa('f'-'a')
    15.     io_dec.fp_csr := Bool(usingFPU) && DecodeLogic(io_dec.csr, fp_csrs.keys.toList.map(_.U), (read_mapping -- fp_csrs.keys.toList).keys.toList.map(_.U))
    16.     io_dec.rocc_illegal := io.status.xs === 0 || !reg_misa('x'-'a')
    17.     io_dec.read_illegal := reg_mstatus.prv < io_dec.csr(9,8) ||
    18.       !decodeAny(read_mapping) ||
    19.       io_dec.csr === CSRs.sptbr && !allow_sfence_vma ||
    20.       (io_dec.csr.inRange(CSR.firstCtr, CSR.firstCtr + CSR.nCtr) || io_dec.csr.inRange(CSR.firstCtrH, CSR.firstCtrH + CSR.nCtr)) && !allow_counter ||
    21.       Bool(usingDebug) && decodeAny(debug_csrs) && !reg_debug ||
    22.       io_dec.fp_csr && io_dec.fp_illegal
    23.     io_dec.write_illegal := io_dec.csr(11,10).andR
    24.     io_dec.write_flush := !(io_dec.csr >= CSRs.mscratch && io_dec.csr <= CSRs.mbadaddr || io_dec.csr >= CSRs.sscratch && io_dec.csr <= CSRs.sbadaddr)
    25.     io_dec.system_illegal := reg_mstatus.prv < io_dec.csr(9,8) ||
    26.       is_wfi && !allow_wfi ||
    27.       is_ret && !allow_sret ||
    28.       is_sfence && !allow_sfence_vma
    29.   }
    复制代码

    7.CSR异常原因

    1. val cause =
    2.     Mux(insn_call, reg_mstatus.prv + Causes.user_ecall,
    3.     Mux[UInt](insn_break, Causes.breakpoint, io.cause))
    4.   //异常尾代码
    5.   val cause_lsbs = cause(io.trace.head.cause.getWidth-1, 0)
    6.   //调试中断原因
    7.   val causeIsDebugInt = cause(xLen-1) && cause_lsbs === CSR.debugIntCause
    8.   //调试异常Trigger原因
    9.   val causeIsDebugTrigger = !cause(xLen-1) && cause_lsbs === CSR.debugTriggerCause
    10.   //调试异常Break原因
    11.   val causeIsDebugBreak = !cause(xLen-1) && insn_break && Cat(reg_dcsr.ebreakm, reg_dcsr.ebreakh, reg_dcsr.ebreaks, reg_dcsr.ebreaku)(reg_mstatus.prv)
    12.   //是否陷入调试模式
    13.   val trapToDebug = Bool(usingDebug) && (reg_singleStepped || causeIsDebugInt || causeIsDebugTrigger || causeIsDebugBreak || reg_debug)
    14.   //调试模式:陷入地址确定
    15.   val debugTVec = Mux(reg_debug, Mux(insn_break, UInt(0x800), UInt(0x808)), UInt(0x800))
    16.   //委托挂起情况
    17.   val delegate = Bool(usingVM) && reg_mstatus.prv <= PRV.S && Mux(cause(xLen-1), reg_mideleg(cause_lsbs), reg_medeleg(cause_lsbs))
    18.   val mtvecBaseAlign = 2
    19.   val mtvecInterruptAlign = {
    20.     require(reg_mip.getWidth <= xLen)
    21.     log2Ceil(xLen)
    22.   }

    23. //不是调试模式:陷入地址确定
    24.   val notDebugTVec = {
    25.     val base = Mux(delegate, reg_stvec.sextTo(vaddrBitsExtended), reg_mtvec)
    26.     val interruptOffset = cause(mtvecInterruptAlign-1, 0) << mtvecBaseAlign
    27.     val interruptVec = Cat(base >> (mtvecInterruptAlign + mtvecBaseAlign), interruptOffset)
    28.     val doVector = base(0) && cause(cause.getWidth-1) && (cause_lsbs >> mtvecInterruptAlign) === 0
    29.     Mux(doVector, interruptVec, base)
    30.   }

    31. //陷入地址确定
    32.   val tvec = Mux(trapToDebug, debugTVec, notDebugTVec)
    33.   io.evec := tvec
    34.   io.ptbr := reg_sptbr
    35.   io.eret := insn_call || insn_break || insn_ret
    36.   io.singleStep := reg_dcsr.step && !reg_debug
    37.   io.status := reg_mstatus
    38.   io.status.sd := io.status.fs.andR || io.status.xs.andR
    39.   io.status.debug := reg_debug
    40.   io.status.isa := reg_misa
    41.   io.status.uxl := (if (usingUser) log2Ceil(xLen) - 4 else 0)
    42.   io.status.sxl := (if (usingVM) log2Ceil(xLen) - 4 else 0)
    43.   io.status.dprv := Reg(next = Mux(reg_mstatus.mprv && !reg_debug, reg_mstatus.mpp, reg_mstatus.prv))
    44.   if (xLen == 32)
    45.     io.status.sd_rv32 := io.status.sd
    复制代码

    8.异常的CSR操作(CALL、BREAK、外部异常)

    1. //当发生异常时,操作
    2.   when (exception) {
    3.     when (trapToDebug) {
    4.       when (!reg_debug) {
    5.         reg_debug := true
    6.         reg_dpc := epc
    7.         reg_dcsr.cause := Mux(reg_singleStepped, 4, Mux(causeIsDebugInt, 3, Mux[UInt](causeIsDebugTrigger, 2, 1)))
    8.         reg_dcsr.prv := trimPrivilege(reg_mstatus.prv)
    9.         new_prv := PRV.M
    10.       }
    11.     }.elsewhen (delegate) {
    12.       reg_sepc := epc
    13.       reg_scause := cause
    14.       xcause_dest := sCause
    15.       reg_sbadaddr := io.tval
    16.       reg_mstatus.spie := reg_mstatus.sie
    17.       reg_mstatus.spp := reg_mstatus.prv
    18.       reg_mstatus.sie := false
    19.       new_prv := PRV.S
    20.     }.otherwise {
    21.       reg_mepc := epc
    22.       reg_mcause := cause
    23.       xcause_dest := mCause
    24.       reg_mbadaddr := io.tval
    25.       reg_mstatus.mpie := reg_mstatus.mie
    26.       reg_mstatus.mpp := trimPrivilege(reg_mstatus.prv)
    27.       reg_mstatus.mie := false
    28.       new_prv := PRV.M
    29.     }
    30.   }
    复制代码

    9.异常的CSR操作(XRET)

    1. when (insn_ret) {
    2.     when (Bool(usingVM) && !io.rw.addr(9)) {
    3.       //SRET
    4.       reg_mstatus.sie := reg_mstatus.spie
    5.       reg_mstatus.spie := true
    6.       reg_mstatus.spp := PRV.U
    7.       new_prv := reg_mstatus.spp
    8.       io.evec := readEPC(reg_sepc)
    9.     }.elsewhen (Bool(usingDebug) && io.rw.addr(10)) {
    10.       //DRET
    11.       new_prv := reg_dcsr.prv
    12.       reg_debug := false
    13.       io.evec := readEPC(reg_dpc)
    14.     }.otherwise {
    15.       //MRET
    16.       reg_mstatus.mie := reg_mstatus.mpie
    17.       reg_mstatus.mpie := true
    18.       reg_mstatus.mpp := legalizePrivilege(PRV.U)
    19.       new_prv := reg_mstatus.mpp
    20.       io.evec := readEPC(reg_mepc)
    21.     }
    22.   }
    复制代码
    本篇完,感谢关注:RISC-V单片机中文网





    上一篇:RISC-V架构是否支持中断嵌套?
    下一篇:picoRV32 (RISC-V) GCC 编译环境
    RISCV作者优文
    全球首家只专注于RISC-V单片机行业应用的中文网站
    回复

    使用道具 举报

    高级模式
    B Color Image Link Quote Code Smilies

    本版积分规则

    关闭

    RISC-V单片机中文网上一条 /2 下一条



    版权及免责声明|RISC-V单片机中文网 |网站地图

    GMT+8, 2024-3-29 03:55 , Processed in 0.559067 second(s), 45 queries .

    快速回复 返回顶部 返回列表