名称 | 方向 | 类型 | 作用 |
---|---|---|---|
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结构
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(_))
(1)复位后mstatus;mpp:中断前级别:机器模式;prv:内存可访问级别:机器模式
val reset_mstatus = Wire(init=new MStatus().fromBits(0))
reset_mstatus.mpp := PRV.M
reset_mstatus.prv := PRV.M
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
//地址匹配情况
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)
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)
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
}
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
//当发生异常时,操作
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
}
}
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)
}
}