Add provisional breakpoint support
This commit is contained in:
		
							
								
								
									
										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)), | ||||
|   | ||||
		Reference in New Issue
	
	Block a user