Add provisional breakpoint support
This commit is contained in:
parent
4f2e2480a8
commit
e3c17b5f74
45
rocket/src/main/scala/breakpoint.scala
Normal file
45
rocket/src/main/scala/breakpoint.scala
Normal file
@ -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 }
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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)),
|
||||
|
Loading…
Reference in New Issue
Block a user