皋陶 发表于 2020-8-23 20:50:20

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

本帖最后由 皋陶 于 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结构
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)
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): 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(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(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单片机中文网

页: [1]
查看完整版本: RISC-V:控制与状态寄存器(CSR)