From 9949347569beae5ee1a60071b03fb49acf2bd52c Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Wed, 1 Jun 2016 16:57:10 -0700 Subject: [PATCH] First stab at debug interrupts --- rocket/src/main/scala/csr.scala | 89 +++++++++++++++++++++--- rocket/src/main/scala/idecode.scala | 15 +++- rocket/src/main/scala/instructions.scala | 15 ++-- rocket/src/main/scala/rocket.scala | 4 ++ rocket/src/main/scala/tlb.scala | 2 +- rocket/src/main/scala/util.scala | 1 + 6 files changed, 108 insertions(+), 18 deletions(-) diff --git a/rocket/src/main/scala/csr.scala b/rocket/src/main/scala/csr.scala index aa1ea014..7713d536 100644 --- a/rocket/src/main/scala/csr.scala +++ b/rocket/src/main/scala/csr.scala @@ -11,6 +11,7 @@ import scala.math._ import junctions.AddrHashMap class MStatus extends Bundle { + val debug = Bool() // not truly part of mstatus, but convenient val prv = UInt(width = PRV.SZ) // not truly part of mstatus, but convenient val sd = Bool() val zero3 = UInt(width = 31) @@ -35,6 +36,26 @@ class MStatus extends Bundle { val uie = Bool() } +class DCSR extends Bundle { + val xdebugver = UInt(width = 2) + val ndreset = Bool() + val fullreset = Bool() + val hwbpcount = UInt(width = 12) + val ebreakm = Bool() + val ebreakh = Bool() + val ebreaks = Bool() + val ebreaku = Bool() + val zero2 = Bool() + val stopcycle = Bool() + val stoptime = Bool() + val cause = UInt(width = 3) + val debugint = Bool() + val zero1 = Bool() + val halt = Bool() + val step = Bool() + val prv = UInt(width = PRV.SZ) +} + class MIP extends Bundle { val rocc = Bool() val meip = Bool() @@ -116,6 +137,11 @@ class CSRFile(implicit p: Parameters) extends CoreModule()(p) reset_mstatus.prv := PRV.M val reg_mstatus = Reg(init=reset_mstatus) + val reset_dcsr = Wire(init=new DCSR().fromBits(0)) + reset_dcsr.xdebugver := 1 + reset_dcsr.prv := PRV.M + val reg_dcsr = Reg(init=reset_dcsr) + val (supported_interrupts, delegable_interrupts) = { val sup = Wire(init=new MIP().fromBits(0)) sup.ssip := Bool(p(UseVM)) @@ -141,6 +167,10 @@ class CSRFile(implicit p: Parameters) extends CoreModule()(p) Causes.fault_store, Causes.user_ecall).map(1 << _).sum) + val reg_debug = Reg(init=Bool(false)) + val reg_dpc = Reg(UInt(width = vaddrBitsExtended)) + val reg_dscratch = Reg(UInt(width = xLen)) + val reg_mie = Reg(init=UInt(0, xLen)) val reg_mideleg = Reg(init=UInt(0, xLen)) val reg_medeleg = Reg(init=UInt(0, xLen)) @@ -171,11 +201,20 @@ class CSRFile(implicit p: Parameters) extends CoreModule()(p) val read_mip = mip.toBits & supported_interrupts val pending_interrupts = read_mip & reg_mie - val m_interrupts = Mux(reg_mstatus.prv < PRV.M || (reg_mstatus.prv === PRV.M && 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 m_interrupts = Mux(!reg_debug && (reg_mstatus.prv < PRV.M || (reg_mstatus.prv === PRV.M && reg_mstatus.mie)), pending_interrupts & ~reg_mideleg, UInt(0)) + val s_interrupts = Mux(!reg_debug && (reg_mstatus.prv < PRV.S || (reg_mstatus.prv === PRV.S && reg_mstatus.sie)), pending_interrupts & reg_mideleg, UInt(0)) val all_interrupts = m_interrupts | s_interrupts + val interruptMSB = BigInt(1) << (xLen-1) + val interruptCause = interruptMSB + PriorityEncoder(all_interrupts) io.interrupt := all_interrupts.orR - io.interrupt_cause := (io.interrupt << (xLen-1)) + PriorityEncoder(all_interrupts) + io.interrupt_cause := interruptCause + + val debugIntCause = reg_mip.getWidth + // debug interrupts are only masked by being in debug mode + when (Bool(usingDebug) && reg_dcsr.debugint && !reg_debug) { + io.interrupt := true + io.interrupt_cause := interruptMSB + debugIntCause + } val system_insn = io.rw.cmd === CSR.I val cpu_ren = io.rw.cmd =/= CSR.N && !system_insn @@ -212,6 +251,12 @@ class CSRFile(implicit p: Parameters) extends CoreModule()(p) CSRs.mcause -> reg_mcause, CSRs.mhartid -> io.prci.id) + if (usingDebug) { + read_mapping += CSRs.dcsr -> reg_dcsr.toBits + read_mapping += CSRs.dpc -> reg_dpc.toBits + read_mapping += CSRs.dscratch -> reg_dscratch.toBits + } + if (usingFPU) { read_mapping += CSRs.fflags -> reg_fflags read_mapping += CSRs.frm -> reg_frm @@ -278,8 +323,9 @@ class CSRFile(implicit p: Parameters) extends CoreModule()(p) val fp_csr = if (usingFPU) decoded_addr(CSRs.fflags) || decoded_addr(CSRs.frm) || decoded_addr(CSRs.fcsr) else Bool(false) - val csr_addr_priv = io.rw.addr(9,8) - val priv_sufficient = reg_mstatus.prv >= csr_addr_priv + val csr_debug = Bool(usingDebug) && io.rw.addr(5) + val csr_addr_priv = Cat(io.rw.addr(5), io.rw.addr(9,8)) + val priv_sufficient = Cat(reg_debug, reg_mstatus.prv) >= csr_addr_priv val read_only = io.rw.addr(11,10).andR val cpu_wen = cpu_ren && io.rw.cmd =/= CSR.R && priv_sufficient val wen = cpu_wen && !read_only @@ -308,9 +354,12 @@ class CSRFile(implicit p: Parameters) extends CoreModule()(p) Mux(insn_call, reg_mstatus.prv + Causes.user_ecall, Mux[UInt](insn_break, Causes.breakpoint, Causes.illegal_instruction))) val cause_lsbs = cause(log2Up(xLen)-1,0) + val causeIsDebugInt = cause(xLen-1) && cause_lsbs === debugIntCause + val causeIsDebugBreak = insn_break && Cat(reg_dcsr.ebreakm, reg_dcsr.ebreakh, reg_dcsr.ebreaks, reg_dcsr.ebreaku)(reg_mstatus.prv) + val trapToDebug = Bool(usingDebug) && (causeIsDebugInt || causeIsDebugBreak || reg_debug) val delegate = Bool(p(UseVM)) && reg_mstatus.prv < PRV.M && Mux(cause(xLen-1), reg_mideleg(cause_lsbs), reg_medeleg(cause_lsbs)) - val tvec = Mux(delegate, reg_stvec.sextTo(vaddrBitsExtended), reg_mtvec) - val epc = Mux(Bool(p(UseVM)) && !csr_addr_priv(1), reg_sepc, reg_mepc) + val tvec = Mux(trapToDebug, UInt(0x800), Mux(delegate, reg_stvec.sextTo(vaddrBitsExtended), reg_mtvec)) + val epc = Mux(csr_debug, reg_dpc, Mux(Bool(p(UseVM)) && !csr_addr_priv(1), reg_sepc, reg_mepc)) io.fatc := insn_sfence_vm io.evec := Mux(io.exception || csr_xcpt, tvec, epc) io.ptbr := reg_sptbr @@ -318,6 +367,7 @@ class CSRFile(implicit p: Parameters) extends CoreModule()(p) io.eret := insn_ret io.status := reg_mstatus io.status.sd := io.status.fs.andR || io.status.xs.andR + io.status.debug := reg_debug if (xLen == 32) io.status.sd_rv32 := io.status.sd @@ -336,7 +386,12 @@ class CSRFile(implicit p: Parameters) extends CoreModule()(p) val epc = ~(~io.pc | (coreInstBytes-1)) val pie = read_mstatus(reg_mstatus.prv) - when (delegate) { + when (trapToDebug) { + reg_debug := true + reg_dpc := epc + reg_dcsr.cause := Mux(causeIsDebugInt, UInt(3), UInt(1)) + reg_dcsr.prv := reg_mstatus.prv + }.elsewhen (delegate) { reg_sepc := epc reg_scause := cause reg_sbadaddr := badaddr @@ -361,6 +416,9 @@ class CSRFile(implicit p: Parameters) extends CoreModule()(p) reg_mstatus.spie := false reg_mstatus.spp := PRV.U reg_mstatus.prv := reg_mstatus.spp + }.elsewhen (csr_debug) { + reg_mstatus.prv := reg_dcsr.prv + reg_debug := false }.otherwise { when (reg_mstatus.mpp(1)) { reg_mstatus.mie := reg_mstatus.mpie } .elsewhen (Bool(usingVM) && reg_mstatus.mpp(0)) { reg_mstatus.sie := reg_mstatus.mpie } @@ -382,13 +440,14 @@ class CSRFile(implicit p: Parameters) extends CoreModule()(p) reg_fflags := reg_fflags | io.fcsr_flags.bits } + val supportedModes = Vec((PRV.M +: (if (usingUser) Some(PRV.U) else None) ++: (if (usingVM) Seq(PRV.S) else Nil)).map(UInt(_))) + when (wen) { when (decoded_addr(CSRs.mstatus)) { val new_mstatus = new MStatus().fromBits(wdata) reg_mstatus.mie := new_mstatus.mie reg_mstatus.mpie := new_mstatus.mpie - val supportedModes = Vec((PRV.M +: (if (usingUser) Some(PRV.U) else None) ++: (if (usingVM) Seq(PRV.S) else Nil)).map(UInt(_))) if (supportedModes.size > 1) { reg_mstatus.mprv := new_mstatus.mprv when (supportedModes contains new_mstatus.mpp) { reg_mstatus.mpp := new_mstatus.mpp } @@ -428,6 +487,17 @@ class CSRFile(implicit p: Parameters) extends CoreModule()(p) when (decoded_addr(CSRs.frm)) { reg_frm := wdata } when (decoded_addr(CSRs.fcsr)) { reg_fflags := wdata; reg_frm := wdata >> reg_fflags.getWidth } } + if (usingDebug) { + when (decoded_addr(CSRs.dcsr)) { + val new_dcsr = new DCSR().fromBits(wdata) + reg_dcsr.ebreakm := new_dcsr.ebreakm + if (usingVM) reg_dcsr.ebreaks := new_dcsr.ebreaks + if (usingUser) reg_dcsr.ebreaku := new_dcsr.ebreaku + if (supportedModes.size > 1) reg_dcsr.prv := new_dcsr.prv + } + when (decoded_addr(CSRs.dpc)) { reg_dpc := ~(~wdata | (coreInstBytes-1)) } + when (decoded_addr(CSRs.dscratch)) { reg_dscratch := wdata } + } if (usingVM) { when (decoded_addr(CSRs.sstatus)) { val new_sstatus = new MStatus().fromBits(wdata) @@ -455,6 +525,7 @@ class CSRFile(implicit p: Parameters) extends CoreModule()(p) } reg_mip := io.prci.interrupts + reg_dcsr.debugint := io.prci.interrupts.debug io.rocc.csr.waddr := io.rw.addr io.rocc.csr.wdata := wdata diff --git a/rocket/src/main/scala/idecode.scala b/rocket/src/main/scala/idecode.scala index 33319e93..2168922c 100644 --- a/rocket/src/main/scala/idecode.scala +++ b/rocket/src/main/scala/idecode.scala @@ -110,10 +110,8 @@ class IDecode(implicit val p: Parameters) extends DecodeConstants FENCE-> List(Y,N,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, MT_X, N,N,N,N,N,N,CSR.N,N,Y,N), FENCE_I-> List(Y,N,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, Y,M_FLUSH_ALL,MT_X, N,N,N,N,N,N,CSR.N,Y,N,N), - SFENCE_VM-> List(Y,N,N,N,N,N,N,X,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, MT_X, N,N,N,N,N,N,CSR.I,N,N,N), SCALL-> List(Y,N,N,N,N,N,N,X,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, MT_X, N,N,N,N,N,N,CSR.I,N,N,N), SBREAK-> List(Y,N,N,N,N,N,N,X,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, MT_X, N,N,N,N,N,N,CSR.I,N,N,N), - SRET-> List(Y,N,N,N,N,N,N,X,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, MT_X, N,N,N,N,N,N,CSR.I,N,N,N), MRET-> List(Y,N,N,N,N,N,N,X,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, MT_X, N,N,N,N,N,N,CSR.I,N,N,N), WFI-> List(Y,N,N,N,N,N,N,X,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, MT_X, N,N,N,N,N,N,CSR.I,N,N,N), CSRRW-> List(Y,N,N,N,N,N,N,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, N,M_X, MT_X, N,N,N,N,N,Y,CSR.W,N,N,N), @@ -124,6 +122,19 @@ class IDecode(implicit val p: Parameters) extends DecodeConstants CSRRCI-> List(Y,N,N,N,N,N,N,N,A2_IMM, A1_ZERO,IMM_Z, DW_XPR,FN_ADD, N,M_X, MT_X, N,N,N,N,N,Y,CSR.C,N,N,N)) } +class SDecode(implicit val p: Parameters) extends DecodeConstants +{ + val table: Array[(BitPat, List[BitPat])] = Array( + SFENCE_VM-> List(Y,N,N,N,N,N,N,X,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, MT_X, N,N,N,N,N,N,CSR.I,N,N,N), + SRET-> List(Y,N,N,N,N,N,N,X,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, MT_X, N,N,N,N,N,N,CSR.I,N,N,N)) +} + +class DebugDecode(implicit val p: Parameters) extends DecodeConstants +{ + val table: Array[(BitPat, List[BitPat])] = Array( + DRET-> List(Y,N,N,N,N,N,N,X,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, MT_X, N,N,N,N,N,N,CSR.I,N,N,N)) +} + class I64Decode(implicit val p: Parameters) extends DecodeConstants { val table: Array[(BitPat, List[BitPat])] = Array( diff --git a/rocket/src/main/scala/instructions.scala b/rocket/src/main/scala/instructions.scala index 808505d5..275e5194 100644 --- a/rocket/src/main/scala/instructions.scala +++ b/rocket/src/main/scala/instructions.scala @@ -98,6 +98,7 @@ object Instructions { def SRET = BitPat("b00010000001000000000000001110011") def HRET = BitPat("b00100000001000000000000001110011") def MRET = BitPat("b00110000001000000000000001110011") + def DRET = BitPat("b01111011001000000000000001110011") def SFENCE_VM = BitPat("b000100000100?????000000001110011") def WFI = BitPat("b00010000010100000000000001110011") def CSRRW = BitPat("b?????????????????001?????1110011") @@ -272,7 +273,6 @@ object CSRs { val mcause = 0x342 val mbadaddr = 0x343 val mip = 0x344 - val mipi = 0x345 val mucounteren = 0x310 val mscounteren = 0x311 val mucycle_delta = 0x700 @@ -281,6 +281,9 @@ object CSRs { val mscycle_delta = 0x704 val mstime_delta = 0x705 val msinstret_delta = 0x706 + val dcsr = 0x7b0 + val dpc = 0x7b1 + val dscratch = 0x7b2 val mcycle = 0xf00 val mtime = 0xf01 val minstret = 0xf02 @@ -289,8 +292,6 @@ object CSRs { val marchid = 0xf12 val mimpid = 0xf13 val mhartid = 0xf14 - val mtohost = 0x7c0 - val mfromhost = 0x7c1 val mreset = 0x7c2 val cycleh = 0xc80 val timeh = 0xc81 @@ -302,6 +303,7 @@ object CSRs { val mstime_deltah = 0x785 val msinstret_deltah = 0x786 val mcycleh = 0xf80 + val mtimeh = 0xf81 val minstreth = 0xf82 val all = { val res = collection.mutable.ArrayBuffer[Int]() @@ -334,7 +336,6 @@ object CSRs { res += mcause res += mbadaddr res += mip - res += mipi res += mucounteren res += mscounteren res += mucycle_delta @@ -343,6 +344,9 @@ object CSRs { res += mscycle_delta res += mstime_delta res += msinstret_delta + res += dcsr + res += dpc + res += dscratch res += mcycle res += mtime res += minstret @@ -351,8 +355,6 @@ object CSRs { res += marchid res += mimpid res += mhartid - res += mtohost - res += mfromhost res += mreset res.toArray } @@ -368,6 +370,7 @@ object CSRs { res += mstime_deltah res += msinstret_deltah res += mcycleh + res += mtimeh res += minstreth res.toArray } diff --git a/rocket/src/main/scala/rocket.scala b/rocket/src/main/scala/rocket.scala index e365b217..160fa632 100644 --- a/rocket/src/main/scala/rocket.scala +++ b/rocket/src/main/scala/rocket.scala @@ -15,6 +15,7 @@ case object FetchWidth extends Field[Int] case object RetireWidth extends Field[Int] case object UseVM extends Field[Boolean] case object UseUser extends Field[Boolean] +case object UseDebug extends Field[Boolean] case object UseAtomics extends Field[Boolean] case object UsePerfCounters extends Field[Boolean] case object FastLoadWord extends Field[Boolean] @@ -34,6 +35,7 @@ trait HasCoreParameters extends HasAddrMapParameters { val usingVM = p(UseVM) val usingUser = p(UseUser) + val usingDebug = p(UseDebug) val usingFPU = p(UseFPU) val usingAtomics = p(UseAtomics) val usingFDivSqrt = p(FDivSqrt) @@ -129,6 +131,8 @@ class Rocket(implicit p: Parameters) extends CoreModule()(p) { (if (usingFPU && usingFDivSqrt) Some(new FDivSqrtDecode) else None) ++: (if (usingRoCC) Some(new RoCCDecode) else None) ++: (if (xLen > 32) Some(new I64Decode) else None) ++: + (if (usingVM) Some(new SDecode) else None) ++: + (if (usingDebug) Some(new DebugDecode) else None) ++: Seq(new IDecode) } flatMap(_.table) diff --git a/rocket/src/main/scala/tlb.scala b/rocket/src/main/scala/tlb.scala index 99742a56..cb607ccd 100644 --- a/rocket/src/main/scala/tlb.scala +++ b/rocket/src/main/scala/tlb.scala @@ -128,7 +128,7 @@ class TLB(implicit p: Parameters) extends TLBModule()(p) { val do_mprv = io.ptw.status.mprv && !io.req.bits.instruction val priv = Mux(do_mprv, io.ptw.status.mpp, io.ptw.status.prv) val priv_s = priv === PRV.S - val priv_uses_vm = priv <= PRV.S + val priv_uses_vm = priv <= PRV.S && !io.ptw.status.debug val req_xwr = Cat(!r_req.store, r_req.store, !(r_req.instruction || r_req.store)) val ur_bits = ur_array.toBits diff --git a/rocket/src/main/scala/util.scala b/rocket/src/main/scala/util.scala index 1dd6eac1..ea6aed48 100644 --- a/rocket/src/main/scala/util.scala +++ b/rocket/src/main/scala/util.scala @@ -10,6 +10,7 @@ import cde.{Parameters, Field} object Util { implicit def uintToBitPat(x: UInt): BitPat = BitPat(x) implicit def intToUInt(x: Int): UInt = UInt(x) + implicit def bigIntToUInt(x: BigInt): UInt = UInt(x) implicit def booleanToBool(x: Boolean): Bits = Bool(x) implicit def intSeqToUIntSeq(x: Seq[Int]): Seq[UInt] = x.map(UInt(_)) implicit def seqToVec[T <: Data](x: Seq[T]): Vec[T] = Vec(x)