From e3c17b5f74f8dad94c3f559fb9d4f08be963053b Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Wed, 8 Jun 2016 20:19:52 -0700 Subject: [PATCH] Add provisional breakpoint support --- rocket/src/main/scala/breakpoint.scala | 45 ++++++++++++++++++++++++ rocket/src/main/scala/csr.scala | 36 +++++++++++++++++-- rocket/src/main/scala/instructions.scala | 8 +++++ rocket/src/main/scala/rocket.scala | 14 ++++++++ 4 files changed, 101 insertions(+), 2 deletions(-) create mode 100644 rocket/src/main/scala/breakpoint.scala diff --git a/rocket/src/main/scala/breakpoint.scala b/rocket/src/main/scala/breakpoint.scala new file mode 100644 index 00000000..92c2430d --- /dev/null +++ b/rocket/src/main/scala/breakpoint.scala @@ -0,0 +1,45 @@ +// See LICENSE for license details. + +package rocket + +import Chisel._ +import Util._ +import cde.Parameters + +class BPControl extends Bundle { + val matchcond = UInt(width = 2) + val m = Bool() + val h = Bool() + val s = Bool() + val u = Bool() + val r = Bool() + val w = Bool() + val x = Bool() +} + +class BreakpointUnit(implicit p: Parameters) extends CoreModule()(p) { + val io = new Bundle { + val bpcontrol = Vec(p(NBreakpoints), new BPControl).asInput + val bpaddress = Vec(p(NBreakpoints), UInt(width = vaddrBits)).asInput + val pc = UInt(INPUT, vaddrBits) + val ea = UInt(INPUT, vaddrBits) + val xcpt_if = Bool(OUTPUT) + val xcpt_ld = Bool(OUTPUT) + val xcpt_st = Bool(OUTPUT) + } + + io.xcpt_if := false + io.xcpt_ld := false + io.xcpt_st := false + + for (((bpc, bpa), i) <- io.bpcontrol zip io.bpaddress zipWithIndex) { + var mask: UInt = bpc.matchcond(1) + for (i <- 1 until log2Ceil(16)) + mask = Cat(mask(i-1) && bpa(i-1), mask) + + def matches(x: UInt) = (~x | mask) === (~bpa | mask) + when (matches(io.pc) && bpc.x) { io.xcpt_if := true } + when (matches(io.ea) && bpc.r) { io.xcpt_ld := true } + when (matches(io.ea) && bpc.w) { io.xcpt_st := true } + } +} diff --git a/rocket/src/main/scala/csr.scala b/rocket/src/main/scala/csr.scala index 47c4a7e2..b6fc328a 100644 --- a/rocket/src/main/scala/csr.scala +++ b/rocket/src/main/scala/csr.scala @@ -7,7 +7,6 @@ import Util._ import Instructions._ import cde.{Parameters, Field} import uncore._ -import scala.math._ import junctions.AddrMap class MStatus extends Bundle { @@ -126,6 +125,8 @@ class CSRFileIO(implicit p: Parameters) extends CoreBundle { val rocc = new RoCCInterface().flip val interrupt = Bool(OUTPUT) val interrupt_cause = UInt(OUTPUT, xLen) + val bpcontrol = Vec(p(NBreakpoints), new BPControl).asOutput + val bpaddress = Vec(p(NBreakpoints), UInt(width = vaddrBits)).asOutput } class CSRFile(implicit p: Parameters) extends CoreModule()(p) @@ -171,6 +172,10 @@ class CSRFile(implicit p: Parameters) extends CoreModule()(p) val reg_dpc = Reg(UInt(width = vaddrBitsExtended)) val reg_dscratch = Reg(UInt(width = xLen)) + val reg_tdrselect = Reg(init=UInt(0, log2Up(p(NBreakpoints)))) + val reg_bpcontrol = Reg(Vec(p(NBreakpoints), new BPControl)) + val reg_bpaddress = Reg(Vec(p(NBreakpoints), UInt(width = vaddrBits))) + val reg_mie = Reg(init=UInt(0, xLen)) val reg_mideleg = Reg(init=UInt(0, xLen)) val reg_medeleg = Reg(init=UInt(0, xLen)) @@ -208,6 +213,8 @@ class CSRFile(implicit p: Parameters) extends CoreModule()(p) val interruptCause = interruptMSB + PriorityEncoder(all_interrupts) io.interrupt := all_interrupts.orR io.interrupt_cause := interruptCause + io.bpcontrol := reg_bpcontrol + io.bpaddress := reg_bpaddress val debugIntCause = reg_mip.getWidth // debug interrupts are only masked by being in debug mode @@ -229,6 +236,9 @@ class CSRFile(implicit p: Parameters) extends CoreModule()(p) val read_mstatus = io.status.toBits()(xLen-1,0) val read_mapping = collection.mutable.LinkedHashMap[Int,Bits]( + CSRs.tdrselect -> reg_tdrselect, + CSRs.tdrdata1 -> (if (p(NBreakpoints) > 0) reg_bpcontrol(reg_tdrselect).toBits else UInt(0)), + CSRs.tdrdata2 -> (if (p(NBreakpoints) > 0) reg_bpaddress(reg_tdrselect) else UInt(0)), CSRs.mimpid -> UInt(0), CSRs.marchid -> UInt(0), CSRs.mvendorid -> UInt(0), @@ -324,7 +334,7 @@ class CSRFile(implicit p: Parameters) extends CoreModule()(p) if (usingFPU) decoded_addr(CSRs.fflags) || decoded_addr(CSRs.frm) || decoded_addr(CSRs.fcsr) else Bool(false) val csr_debug = Bool(usingDebug) && io.rw.addr(5) - val csr_addr_priv = Cat(io.rw.addr(5), io.rw.addr(9,8)) + val csr_addr_priv = Cat(io.rw.addr(6,5).andR, 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 @@ -523,10 +533,20 @@ class CSRFile(implicit p: Parameters) extends CoreModule()(p) when (decoded_addr(CSRs.mideleg)) { reg_mideleg := wdata & delegable_interrupts } when (decoded_addr(CSRs.medeleg)) { reg_medeleg := wdata & delegable_exceptions } } + if (p(NBreakpoints) > 0) { + when (decoded_addr(CSRs.tdrselect)) { reg_tdrselect := Mux(wdata(log2Up(p(NBreakpoints))-1,0) >= UInt(p(NBreakpoints)), UInt(0), wdata(log2Up(p(NBreakpoints))-1,0)) } + when (decoded_addr(CSRs.tdrdata1)) { + val newBPC = new BPControl().fromBits(wdata) + reg_bpcontrol(reg_tdrselect) := newBPC + reg_bpcontrol(reg_tdrselect).matchcond := newBPC.matchcond | 1 /* exact/range only */ + } + when (decoded_addr(CSRs.tdrdata2)) { reg_bpaddress(reg_tdrselect) := wdata } + } } reg_mip := io.prci.interrupts reg_dcsr.debugint := io.prci.interrupts.debug + reg_dcsr.hwbpcount := UInt(p(NBreakpoints)) io.rocc.csr.waddr := io.rw.addr io.rocc.csr.wdata := wdata @@ -537,4 +557,16 @@ class CSRFile(implicit p: Parameters) extends CoreModule()(p) reg_mstatus.prv := PRV.M reg_mstatus.mprv := false } + + for (bpc <- reg_bpcontrol) { + bpc.h := false + if (!usingVM) bpc.s := false + if (!usingUser) bpc.u := false + if (!usingVM && !usingUser) bpc.m := true + when (reset) { + bpc.r := false + bpc.w := false + bpc.x := false + } + } } diff --git a/rocket/src/main/scala/instructions.scala b/rocket/src/main/scala/instructions.scala index 275e5194..dd0d515f 100644 --- a/rocket/src/main/scala/instructions.scala +++ b/rocket/src/main/scala/instructions.scala @@ -281,6 +281,10 @@ object CSRs { val mscycle_delta = 0x704 val mstime_delta = 0x705 val msinstret_delta = 0x706 + val tdrselect = 0x7a0 + val tdrdata1 = 0x7a1 + val tdrdata2 = 0x7a2 + val tdrdata3 = 0x7a3 val dcsr = 0x7b0 val dpc = 0x7b1 val dscratch = 0x7b2 @@ -344,6 +348,10 @@ object CSRs { res += mscycle_delta res += mstime_delta res += msinstret_delta + res += tdrselect + res += tdrdata1 + res += tdrdata2 + res += tdrdata3 res += dcsr res += dpc res += dscratch diff --git a/rocket/src/main/scala/rocket.scala b/rocket/src/main/scala/rocket.scala index 160fa632..396c4b82 100644 --- a/rocket/src/main/scala/rocket.scala +++ b/rocket/src/main/scala/rocket.scala @@ -28,6 +28,7 @@ case object NCustomMRWCSRs extends Field[Int] case object MtvecWritable extends Field[Boolean] case object MtvecInit extends Field[BigInt] case object ResetVector extends Field[BigInt] +case object NBreakpoints extends Field[Int] trait HasCoreParameters extends HasAddrMapParameters { implicit val p: Parameters @@ -160,6 +161,8 @@ class Rocket(implicit p: Parameters) extends CoreModule()(p) { val mem_reg_flush_pipe = Reg(Bool()) val mem_reg_cause = Reg(UInt()) val mem_reg_slow_bypass = Reg(Bool()) + val mem_reg_load = Reg(Bool()) + val mem_reg_store = Reg(Bool()) val mem_reg_pc = Reg(UInt()) val mem_reg_inst = Reg(Bits()) val mem_reg_wdata = Reg(Bits()) @@ -222,8 +225,15 @@ class Rocket(implicit p: Parameters) extends CoreModule()(p) { val id_do_fence = id_rocc_busy && id_ctrl.fence || id_mem_busy && (id_ctrl.amo && id_amo_aq || id_ctrl.fence_i || id_reg_fence && (id_ctrl.mem || id_ctrl.rocc) || id_csr_en) + val bpu = Module(new BreakpointUnit) + bpu.io.bpcontrol := csr.io.bpcontrol + bpu.io.bpaddress := csr.io.bpaddress + bpu.io.pc := id_pc + bpu.io.ea := mem_reg_wdata + val (id_xcpt, id_cause) = checkExceptions(List( (csr.io.interrupt, csr.io.interrupt_cause), + (bpu.io.xcpt_if, UInt(Causes.breakpoint)), (io.imem.resp.bits.xcpt_if, UInt(Causes.fault_fetch)), (id_illegal_insn, UInt(Causes.illegal_instruction)))) @@ -344,6 +354,8 @@ class Rocket(implicit p: Parameters) extends CoreModule()(p) { when (ex_reg_valid || ex_reg_xcpt_interrupt) { mem_ctrl := ex_ctrl + mem_reg_load := ex_ctrl.mem && isRead(ex_ctrl.mem_cmd) + mem_reg_store := ex_ctrl.mem && isWrite(ex_ctrl.mem_cmd) mem_reg_btb_hit := ex_reg_btb_hit when (ex_reg_btb_hit) { mem_reg_btb_resp := ex_reg_btb_resp } mem_reg_flush_pipe := ex_reg_flush_pipe @@ -359,6 +371,8 @@ class Rocket(implicit p: Parameters) extends CoreModule()(p) { val (mem_xcpt, mem_cause) = checkExceptions(List( (mem_reg_xcpt_interrupt || mem_reg_xcpt, mem_reg_cause), + (mem_reg_valid && mem_reg_load && bpu.io.xcpt_ld, UInt(Causes.breakpoint)), + (mem_reg_valid && mem_reg_store && bpu.io.xcpt_st, UInt(Causes.breakpoint)), (want_take_pc_mem && mem_npc_misaligned, UInt(Causes.misaligned_fetch)), (mem_reg_valid && mem_ctrl.mem && io.dmem.xcpt.ma.st, UInt(Causes.misaligned_store)), (mem_reg_valid && mem_ctrl.mem && io.dmem.xcpt.ma.ld, UInt(Causes.misaligned_load)),