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

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:控制与状态寄存器(CSR))