有人预言,RISC-V或将是继Intel和Arm之后的第三大主流处理器体系。欢迎访问全球首家只专注于RISC-V单片机行业应用的中文网站
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
本帖最后由 皋陶 于 2020-8-26 15:19 编辑
RISC-V:控制与状态寄存器(CSR)
芯片示意图
管脚信息
名称 | 方向 | 类型 | 作用 | interrupts | input | CoreInterrupts | 输入:相关的中断信息 | hartid | input | UInt | 输入:硬件线程id | rw | exchange | 结构体 | 输入:指令 输出:操作的寄存器结果 | decode | exchange | Vec(new CSRDecodeIO) | 输入:指令 输出:异常控制线 | csr_stall | output | Bool | 输出:csr暂停(stall) | eret | output | Bool | 是否执行call、break、ret | singleStep | output | Bool | 输出:单步控制 | status | output | MStatus | 输出:mstatus情况 | ptbr | output | PTBR | 输出:翻译和保护寄存器情况 | evec | output | UInt | 输出:陷入地址 | exception | input | Bool | 输入:外部异常 | retire | input | UInt | 输入:是否有效 | cause | input | UInt | 输入:中断原因 | pc | input | UInt | 输入:当前pc值 | tval | input | UInt | 输入:引起异常的值 | time | output | UInt | 输出:进程执行周期 | fcsr_rm | output | Bits | 输出:浮点读舍入模式 | fcsr_flags | exchange | Valid(Bits) | 交换:浮点读异常标志 | set_fs_dirty | input | Bool | 输入:指定浮点脏标志 | rocc_interrupt | input | Bool | 输入:协处理器中断 | interrupt | output | Bool | 输出:判断是否发生中断 | interrupt_cause | output | UInt | 输出:判断发生中断的原因 | bp | output | Vec(new BP) | 输出:断点情况 | pmp | output | Vec(new PMP) | 输出:内存保护情况 | counters | exchange | Vec(new PerfCounterIO) | 输入:hpmcounter的inc 输出:hpmevent情况 | csrw_counter | output | UInt | 输出:使用的counter下标 | inst | input | Vec(UInt) | 输入:trace命令 | trace | output | Vec(new TracedInstruction) | 输出:trace情况 | customCSRs | exchange | Vec(new CustomCSRIO) | 交换:传统csr |
流程说明1.reg_mip寄存器
(1)reg_mip结构
- class MIP(implicit p: Parameters) extends CoreBundle()(p)
- with HasCoreParameters {
- val lip = Vec(coreParams.nLocalInterrupts, Bool())
- val zero2 = Bool()
- val debug = Bool() // keep in sync with CSR.debugIntCause
- val zero1 = Bool()
- val rocc = Bool()
- val meip = Bool()
- val heip = Bool()
- val seip = Bool()
- val ueip = Bool()
- val mtip = Bool()
- val htip = Bool()
- val stip = Bool()
- val utip = Bool()
- val msip = Bool()
- val hsip = Bool()
- val ssip = Bool()
- val usip = Bool()
- }
- val reg_mip = Reg(new MIP)
复制代码
(2) reg_mip赋值
- val mip = Wire(init=reg_mip)
- mip.lip := (io.interrupts.lip: Seq[Bool])
- mip.mtip := io.interrupts.mtip
- mip.msip := io.interrupts.msip
- mip.meip := io.interrupts.meip
- // seip is the OR of reg_mip.seip and the actual line from the PLIC
- io.interrupts.seip.foreach { mip.seip := reg_mip.seip || RegNext(_)
- 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赋值情况一
- when (decoded_addr(CSRs.mip)) {
- // MIP should be modified based on the value in reg_mip, not the value
- // in read_mip, since read_mip.seip is the OR of reg_mip.seip and
- // io.interrupts.seip. We don't want the value on the PLIC line to
- // inadvertently be OR'd into read_mip.seip.
- val new_mip = readModifyWriteCSR(io.rw.cmd, reg_mip.asUInt, io.rw.wdata).asTypeOf(new MIP)
- if (usingVM) {
- reg_mip.ssip := new_mip.ssip
- reg_mip.stip := new_mip.stip
- reg_mip.seip := new_mip.seip
- }
复制代码
<1> 当操作为修改reg_mip寄存器mip段时,修改的reg_mip寄存器ssip、msip、meip段为对应的数据
(4)reg_mip赋值情况二
- when (decoded_addr(CSRs.sip)) {
- val new_sip = new MIP().fromBits((read_mip & ~reg_mideleg) | (wdata & reg_mideleg))
- reg_mip.ssip := new_sip.ssip
- }
复制代码
<1> 当操作为修改reg_mip寄存器sip段时,修改的reg_mip寄存器ssip段为对应的数据
(5)支持的中断,委托的中断
- val (supported_interrupts, delegable_interrupts) = {
- val sup = Wire(new MIP)
- sup.usip := false
- sup.ssip := Bool(usingVM)
- sup.hsip := false
- sup.msip := true
- sup.utip := false
- sup.stip := Bool(usingVM)
- sup.htip := false
- sup.mtip := true
- sup.ueip := false
- sup.seip := Bool(usingVM)
- sup.heip := false
- sup.meip := true
- sup.rocc := usingRoCC
- sup.zero1 := false
- sup.debug := false
- sup.zero2 := false
- sup.lip foreach { _ := true }
- val supported_high_interrupts = if (io.interrupts.buserror.nonEmpty) UInt(BigInt(1) << CSR.busErrorIntCause) else 0.U
-
- val del = Wire(init=sup)
- del.msip := false
- del.mtip := false
- del.meip := false
- (sup.asUInt | supported_high_interrupts, del.asUInt)
- }
复制代码
(6)中断情况、断点情况、内存保护情况反馈
- val pending_interrupts = high_interrupts | (read_mip & reg_mie)
- val d_interrupts = io.interrupts.debug << CSR.debugIntCause
- val m_interrupts = Mux(reg_mstatus.prv <= PRV.S || reg_mstatus.mie, ~(~pending_interrupts | reg_mideleg), UInt(0))
- val s_interrupts = Mux(reg_mstatus.prv < PRV.S || (reg_mstatus.prv === PRV.S && reg_mstatus.sie), pending_interrupts & reg_mideleg, UInt(0))
- val (anyInterrupt, whichInterrupt) = chooseInterrupt(Seq(s_interrupts, m_interrupts, d_interrupts))
- val interruptMSB = BigInt(1) << (xLen-1)
- val interruptCause = UInt(interruptMSB) + whichInterrupt
- io.interrupt := (anyInterrupt && !io.singleStep || reg_singleStepped) && !reg_debug
- io.interrupt_cause := interruptCause
- io.bp := reg_bp take nBreakpoints
- io.pmp := reg_pmp.map(PMP(_))
复制代码
2.特权模式转换
(1)复位后mstatus;mpp:中断前级别:机器模式;prv:内存可访问级别:机器模式 - val reset_mstatus = Wire(init=new MStatus().fromBits(0))
- reset_mstatus.mpp := PRV.M
- reset_mstatus.prv := PRV.M
复制代码
3.reg_misa寄存器
- val isaMaskString =
- (if (usingMulDiv) "M" else "") +
- (if (usingAtomics) "A" else "") +
- (if (fLen >= 32) "F" else "") +
- (if (fLen >= 64) "D" else "") +
- (if (usingCompressed) "C" else "") +
- (if (usingRoCC) "X" else "")
- val isaString = "I" + isaMaskString +
- (if (usingVM) "S" else "") +
- (if (usingUser) "U" else "")
- val isaMax = (BigInt(log2Ceil(xLen) - 4) << (xLen-2)) | isaStringToMask(isaString)
- val reg_misa = Reg(init=UInt(isaMax))
复制代码- io.status.isa := reg_misa
复制代码
4.CSR写或读逻辑
- //地址匹配情况
- val decoded_addr = read_mapping map { case (k, v) => k -> (io.rw.addr === k) }
- //读或者写操作
- val wdata = readModifyWriteCSR(io.rw.cmd, io.rw.rdata, io.rw.wdata)
复制代码
5.CSR指令
- val system_insn = io.rw.cmd === CSR.I
- val decode_table = Seq(
- SCALL-> List(Y,N,N,N,N),
- SBREAK-> List(N,Y,N,N,N),
- MRET-> List(N,N,Y,N,N),
- WFI-> List(N,N,N,Y,N)) ++ (if (usingDebug) Seq(
- DRET-> List(N,N,Y,N,N)) else Seq()) ++ (if (usingVM) Seq(
- SRET-> List(N,N,Y,N,N),
- SFENCE_VMA->List(N,N,N,N,Y)) else Seq())
- 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异常
- for (io_dec <- io.decode) {
- 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)
- def decodeAny(m: LinkedHashMap[Int,Bits]): Bool = m.map { case(k: Int, _: Bits) => io_dec.csr === k }.reduce(_||_)
- //allow_wfi:未使用虚拟化||当前机器模式||监督模式tw为0
- val allow_wfi = Bool(!usingVM) || reg_mstatus.prv > PRV.S || !reg_mstatus.tw
- //allow_sfence_vma:未使用虚拟化||当前机器模式||监督模式tvm为0
- val allow_sfence_vma = Bool(!usingVM) || reg_mstatus.prv > PRV.S || !reg_mstatus.tvm
- //allow_sret:未使用虚拟化||当前机器模式||监督模式tsr为0
- val allow_sret = Bool(!usingVM) || reg_mstatus.prv > PRV.S || !reg_mstatus.tsr
- val counter_addr = io_dec.csr(log2Ceil(reg_mcounteren.getWidth)-1, 0)
- //allow_counter:当前监督模式||计数使能寄存器地址使能情况
- val allow_counter = (reg_mstatus.prv > PRV.S || reg_mcounteren(counter_addr)) &&
- (reg_mstatus.prv >= PRV.S || reg_scounteren(counter_addr))
- io_dec.fp_illegal := io.status.fs === 0 || !reg_misa('f'-'a')
- 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))
- io_dec.rocc_illegal := io.status.xs === 0 || !reg_misa('x'-'a')
- io_dec.read_illegal := reg_mstatus.prv < io_dec.csr(9,8) ||
- !decodeAny(read_mapping) ||
- io_dec.csr === CSRs.sptbr && !allow_sfence_vma ||
- (io_dec.csr.inRange(CSR.firstCtr, CSR.firstCtr + CSR.nCtr) || io_dec.csr.inRange(CSR.firstCtrH, CSR.firstCtrH + CSR.nCtr)) && !allow_counter ||
- Bool(usingDebug) && decodeAny(debug_csrs) && !reg_debug ||
- io_dec.fp_csr && io_dec.fp_illegal
- io_dec.write_illegal := io_dec.csr(11,10).andR
- io_dec.write_flush := !(io_dec.csr >= CSRs.mscratch && io_dec.csr <= CSRs.mbadaddr || io_dec.csr >= CSRs.sscratch && io_dec.csr <= CSRs.sbadaddr)
- io_dec.system_illegal := reg_mstatus.prv < io_dec.csr(9,8) ||
- is_wfi && !allow_wfi ||
- is_ret && !allow_sret ||
- is_sfence && !allow_sfence_vma
- }
复制代码
7.CSR异常原因
- val cause =
- Mux(insn_call, reg_mstatus.prv + Causes.user_ecall,
- Mux[UInt](insn_break, Causes.breakpoint, io.cause))
- //异常尾代码
- val cause_lsbs = cause(io.trace.head.cause.getWidth-1, 0)
- //调试中断原因
- val causeIsDebugInt = cause(xLen-1) && cause_lsbs === CSR.debugIntCause
- //调试异常Trigger原因
- val causeIsDebugTrigger = !cause(xLen-1) && cause_lsbs === CSR.debugTriggerCause
- //调试异常Break原因
- val causeIsDebugBreak = !cause(xLen-1) && insn_break && Cat(reg_dcsr.ebreakm, reg_dcsr.ebreakh, reg_dcsr.ebreaks, reg_dcsr.ebreaku)(reg_mstatus.prv)
- //是否陷入调试模式
- val trapToDebug = Bool(usingDebug) && (reg_singleStepped || causeIsDebugInt || causeIsDebugTrigger || causeIsDebugBreak || reg_debug)
- //调试模式:陷入地址确定
- val debugTVec = Mux(reg_debug, Mux(insn_break, UInt(0x800), UInt(0x808)), UInt(0x800))
- //委托挂起情况
- val delegate = Bool(usingVM) && reg_mstatus.prv <= PRV.S && Mux(cause(xLen-1), reg_mideleg(cause_lsbs), reg_medeleg(cause_lsbs))
- val mtvecBaseAlign = 2
- val mtvecInterruptAlign = {
- require(reg_mip.getWidth <= xLen)
- log2Ceil(xLen)
- }
- //不是调试模式:陷入地址确定
- val notDebugTVec = {
- val base = Mux(delegate, reg_stvec.sextTo(vaddrBitsExtended), reg_mtvec)
- val interruptOffset = cause(mtvecInterruptAlign-1, 0) << mtvecBaseAlign
- val interruptVec = Cat(base >> (mtvecInterruptAlign + mtvecBaseAlign), interruptOffset)
- val doVector = base(0) && cause(cause.getWidth-1) && (cause_lsbs >> mtvecInterruptAlign) === 0
- Mux(doVector, interruptVec, base)
- }
- //陷入地址确定
- val tvec = Mux(trapToDebug, debugTVec, notDebugTVec)
- io.evec := tvec
- io.ptbr := reg_sptbr
- io.eret := insn_call || insn_break || insn_ret
- io.singleStep := reg_dcsr.step && !reg_debug
- io.status := reg_mstatus
- io.status.sd := io.status.fs.andR || io.status.xs.andR
- io.status.debug := reg_debug
- io.status.isa := reg_misa
- io.status.uxl := (if (usingUser) log2Ceil(xLen) - 4 else 0)
- io.status.sxl := (if (usingVM) log2Ceil(xLen) - 4 else 0)
- io.status.dprv := Reg(next = Mux(reg_mstatus.mprv && !reg_debug, reg_mstatus.mpp, reg_mstatus.prv))
- if (xLen == 32)
- io.status.sd_rv32 := io.status.sd
复制代码
8.异常的CSR操作(CALL、BREAK、外部异常)
- //当发生异常时,操作
- when (exception) {
- when (trapToDebug) {
- when (!reg_debug) {
- reg_debug := true
- reg_dpc := epc
- reg_dcsr.cause := Mux(reg_singleStepped, 4, Mux(causeIsDebugInt, 3, Mux[UInt](causeIsDebugTrigger, 2, 1)))
- reg_dcsr.prv := trimPrivilege(reg_mstatus.prv)
- new_prv := PRV.M
- }
- }.elsewhen (delegate) {
- reg_sepc := epc
- reg_scause := cause
- xcause_dest := sCause
- reg_sbadaddr := io.tval
- reg_mstatus.spie := reg_mstatus.sie
- reg_mstatus.spp := reg_mstatus.prv
- reg_mstatus.sie := false
- new_prv := PRV.S
- }.otherwise {
- reg_mepc := epc
- reg_mcause := cause
- xcause_dest := mCause
- reg_mbadaddr := io.tval
- reg_mstatus.mpie := reg_mstatus.mie
- reg_mstatus.mpp := trimPrivilege(reg_mstatus.prv)
- reg_mstatus.mie := false
- new_prv := PRV.M
- }
- }
复制代码
9.异常的CSR操作(XRET)
- when (insn_ret) {
- when (Bool(usingVM) && !io.rw.addr(9)) {
- //SRET
- reg_mstatus.sie := reg_mstatus.spie
- reg_mstatus.spie := true
- reg_mstatus.spp := PRV.U
- new_prv := reg_mstatus.spp
- io.evec := readEPC(reg_sepc)
- }.elsewhen (Bool(usingDebug) && io.rw.addr(10)) {
- //DRET
- new_prv := reg_dcsr.prv
- reg_debug := false
- io.evec := readEPC(reg_dpc)
- }.otherwise {
- //MRET
- reg_mstatus.mie := reg_mstatus.mpie
- reg_mstatus.mpie := true
- reg_mstatus.mpp := legalizePrivilege(PRV.U)
- new_prv := reg_mstatus.mpp
- io.evec := readEPC(reg_mepc)
- }
- }
复制代码 本篇完,感谢关注:RISC-V单片机中文网
|