From e3b4b5583642391b47d205c7f1b0549d08715d3f Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Fri, 10 Jun 2016 19:55:58 -0700 Subject: [PATCH] Refactor breakpoints and support range comparison (currently disabled) --- rocket/src/main/scala/breakpoint.scala | 41 +++++++++++++++++++------- rocket/src/main/scala/csr.scala | 41 ++++++++++++++------------ rocket/src/main/scala/rocket.scala | 3 +- 3 files changed, 53 insertions(+), 32 deletions(-) diff --git a/rocket/src/main/scala/breakpoint.scala b/rocket/src/main/scala/breakpoint.scala index 65114daf..ee484c28 100644 --- a/rocket/src/main/scala/breakpoint.scala +++ b/rocket/src/main/scala/breakpoint.scala @@ -30,13 +30,28 @@ class BPControl(implicit p: Parameters) extends CoreBundle()(p) { def tdrType = 1 def bpaMaskMax = 4 + def enabled(mstatus: MStatus) = Cat(m, h, s, u)(mstatus.prv) +} + +class BP(implicit p: Parameters) extends CoreBundle()(p) { + val control = new BPControl + val address = UInt(width = vaddrBits) + + def mask(dummy: Int = 0) = { + var mask: UInt = control.bpmatch(1) + for (i <- 1 until control.bpaMaskMax) + mask = Cat(mask(i-1) && address(i-1), mask) + mask + } + + def pow2AddressMatch(x: UInt) = + (~x | mask()) === (~address | mask()) } class BreakpointUnit(implicit p: Parameters) extends CoreModule()(p) { val io = new Bundle { val status = new MStatus().asInput - val bpcontrol = Vec(p(NBreakpoints), new BPControl).asInput - val bpaddress = Vec(p(NBreakpoints), UInt(width = vaddrBits)).asInput + val bp = Vec(p(NBreakpoints), new BP).asInput val pc = UInt(INPUT, vaddrBits) val ea = UInt(INPUT, vaddrBits) val xcpt_if = Bool(OUTPUT) @@ -48,16 +63,20 @@ class BreakpointUnit(implicit p: Parameters) extends CoreModule()(p) { io.xcpt_ld := false io.xcpt_st := false - for (((bpc, bpa), i) <- io.bpcontrol zip io.bpaddress zipWithIndex) { - var mask: UInt = bpc.bpmatch(1) - for (i <- 1 until bpc.bpaMaskMax) - mask = Cat(mask(i-1) && bpa(i-1), mask) + for (bp <- io.bp) { + when (bp.control.enabled(io.status)) { + when (bp.pow2AddressMatch(io.pc) && bp.control.x) { io.xcpt_if := true } + when (bp.pow2AddressMatch(io.ea) && bp.control.r) { io.xcpt_ld := true } + when (bp.pow2AddressMatch(io.ea) && bp.control.w) { io.xcpt_st := true } + } + } - def matches(x: UInt) = (~x | mask) === (~bpa | mask) - when (Cat(bpc.m, bpc.h, bpc.s, bpc.u)(io.status.prv)) { - 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 } + if (!io.bp.isEmpty) for ((bpl, bph) <- io.bp zip io.bp.tail) { + def matches(x: UInt) = !(x < bpl.address) && x < bph.address + when (bph.control.enabled(io.status) && bph.control.bpmatch === 1) { + when (matches(io.pc) && bph.control.x) { io.xcpt_if := true } + when (matches(io.ea) && bph.control.r) { io.xcpt_ld := true } + when (matches(io.ea) && bph.control.w) { io.xcpt_st := true } } } } diff --git a/rocket/src/main/scala/csr.scala b/rocket/src/main/scala/csr.scala index 2016e77e..d3daba09 100644 --- a/rocket/src/main/scala/csr.scala +++ b/rocket/src/main/scala/csr.scala @@ -126,8 +126,7 @@ 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 + val bp = Vec(p(NBreakpoints), new BP).asOutput } class CSRFile(implicit p: Parameters) extends CoreModule()(p) @@ -174,8 +173,7 @@ class CSRFile(implicit p: Parameters) extends CoreModule()(p) val reg_dscratch = Reg(UInt(width = xLen)) val reg_tdrselect = Reg(new TDRSelect) - val reg_bpcontrol = Reg(Vec(p(NBreakpoints), new BPControl)) - val reg_bpaddress = Reg(Vec(p(NBreakpoints), UInt(width = vaddrBits))) + val reg_bp = Reg(Vec(1 << log2Up(p(NBreakpoints)), new BP)) val reg_mie = Reg(init=UInt(0, xLen)) val reg_mideleg = Reg(init=UInt(0, xLen)) @@ -214,8 +212,7 @@ 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 + io.bp := reg_bp take p(NBreakpoints) val debugIntCause = reg_mip.getWidth // debug interrupts are only masked by being in debug mode @@ -238,8 +235,8 @@ class CSRFile(implicit p: Parameters) extends CoreModule()(p) val read_mapping = collection.mutable.LinkedHashMap[Int,Bits]( CSRs.tdrselect -> reg_tdrselect.toBits, - CSRs.tdrdata1 -> (if (p(NBreakpoints) > 0) reg_bpcontrol(reg_tdrselect.tdrindex).toBits else UInt(0)), - CSRs.tdrdata2 -> (if (p(NBreakpoints) > 0) reg_bpaddress(reg_tdrselect.tdrindex) else UInt(0)), + CSRs.tdrdata1 -> reg_bp(reg_tdrselect.tdrindex).control.toBits, + CSRs.tdrdata2 -> reg_bp(reg_tdrselect.tdrindex).address, CSRs.mimpid -> UInt(0), CSRs.marchid -> UInt(0), CSRs.mvendorid -> UInt(0), @@ -340,9 +337,10 @@ class CSRFile(implicit p: Parameters) extends CoreModule()(p) 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 - val wdata = Mux(io.rw.cmd === CSR.S, io.rw.rdata | io.rw.wdata, - Mux(io.rw.cmd === CSR.C, io.rw.rdata & ~io.rw.wdata, - io.rw.wdata)) + + val wdata = (Mux((io.rw.cmd === CSR.S || io.rw.cmd === CSR.C), io.rw.rdata, UInt(0)) | + Mux(io.rw.cmd =/= CSR.C, io.rw.wdata, UInt(0))) & + ~Mux(io.rw.cmd === CSR.C, io.rw.wdata, UInt(0)) val do_system_insn = priv_sufficient && system_insn val opcode = UInt(1) << io.rw.addr(2,0) @@ -525,15 +523,17 @@ class CSRFile(implicit p: Parameters) extends CoreModule()(p) when (decoded_addr(CSRs.medeleg)) { reg_medeleg := wdata & delegable_exceptions } } if (p(NBreakpoints) > 0) { - val canWrite = reg_tdrselect.tdrmode || reg_debug val newTDR = new TDRSelect().fromBits(wdata) - when (decoded_addr(CSRs.tdrselect) && newTDR.tdrindex < newTDR.nTDR) { reg_tdrselect.tdrindex := newTDR.tdrindex } - when (decoded_addr(CSRs.tdrdata1) && canWrite) { - val newBPC = new BPControl().fromBits(wdata) - reg_bpcontrol(reg_tdrselect.tdrindex) := newBPC - reg_bpcontrol(reg_tdrselect.tdrindex).bpmatch := newBPC.bpmatch & 2 /* exact/NAPOT only */ + when (decoded_addr(CSRs.tdrselect)) { reg_tdrselect.tdrindex := newTDR.tdrindex } + + when (reg_tdrselect.tdrmode || reg_debug) { + when (decoded_addr(CSRs.tdrdata1)) { + val newBPC = new BPControl().fromBits(wdata) + reg_bp(reg_tdrselect.tdrindex).control := newBPC + reg_bp(reg_tdrselect.tdrindex).control.bpmatch := newBPC.bpmatch & 2 /* exact/NAPOT only */ + } + when (decoded_addr(CSRs.tdrdata2)) { reg_bp(reg_tdrselect.tdrindex).address := wdata } } - when (decoded_addr(CSRs.tdrdata2) && canWrite) { reg_bpaddress(reg_tdrselect.tdrindex) := wdata } } } @@ -553,7 +553,8 @@ class CSRFile(implicit p: Parameters) extends CoreModule()(p) reg_tdrselect.reserved := 0 reg_tdrselect.tdrmode := true // TODO support D-mode breakpoint theft - for (bpc <- reg_bpcontrol) { + if (reg_bp.isEmpty) reg_tdrselect.tdrindex := 0 + for (bpc <- reg_bp map {_.control}) { bpc.tdrtype := bpc.tdrType bpc.bpamaskmax := bpc.bpaMaskMax bpc.reserved := 0 @@ -568,4 +569,6 @@ class CSRFile(implicit p: Parameters) extends CoreModule()(p) bpc.x := false } } + for (bp <- reg_bp drop p(NBreakpoints)) + bp := new BP().fromBits(0) } diff --git a/rocket/src/main/scala/rocket.scala b/rocket/src/main/scala/rocket.scala index 60ed1634..a8d5a4cf 100644 --- a/rocket/src/main/scala/rocket.scala +++ b/rocket/src/main/scala/rocket.scala @@ -228,8 +228,7 @@ class Rocket(implicit p: Parameters) extends CoreModule()(p) { val bpu = Module(new BreakpointUnit) bpu.io.status := csr.io.status - bpu.io.bpcontrol := csr.io.bpcontrol - bpu.io.bpaddress := csr.io.bpaddress + bpu.io.bp := csr.io.bp bpu.io.pc := id_pc bpu.io.ea := mem_reg_wdata