diff --git a/src/main/scala/diplomaticobjectmodel/logicaltree/RocketLogicalTreeNode.scala b/src/main/scala/diplomaticobjectmodel/logicaltree/RocketLogicalTreeNode.scala index ce96915434..ee13cd8284 100644 --- a/src/main/scala/diplomaticobjectmodel/logicaltree/RocketLogicalTreeNode.scala +++ b/src/main/scala/diplomaticobjectmodel/logicaltree/RocketLogicalTreeNode.scala @@ -95,6 +95,8 @@ class RocketLogicalTreeNode( interruptLatency = 4, nLocalInterrupts = coreParams.nLocalInterrupts, nBreakpoints = coreParams.nBreakpoints, + mcontextWidth = coreParams.mcontextWidth, + scontextWidth = coreParams.scontextWidth, branchPredictor = rocketParams.btb.map(OMBTB.makeOMI), dcache = Some(omDCache), icache = Some(omICache), diff --git a/src/main/scala/diplomaticobjectmodel/model/OMRocketCore.scala b/src/main/scala/diplomaticobjectmodel/model/OMRocketCore.scala index 62a3ec4bca..638db76d01 100644 --- a/src/main/scala/diplomaticobjectmodel/model/OMRocketCore.scala +++ b/src/main/scala/diplomaticobjectmodel/model/OMRocketCore.scala @@ -23,6 +23,8 @@ case class OMRocketCore( interruptLatency: Int, nLocalInterrupts: Int, nBreakpoints: Int, + mcontextWidth: Int, + scontextWidth: Int, branchPredictor: Option[OMRocketBranchPredictor], dcache: Option[OMDCache], icache: Option[OMICache], diff --git a/src/main/scala/rocket/Breakpoint.scala b/src/main/scala/rocket/Breakpoint.scala index 2be5b7fb22..866a7ff5b3 100644 --- a/src/main/scala/rocket/Breakpoint.scala +++ b/src/main/scala/rocket/Breakpoint.scala @@ -31,9 +31,30 @@ class BPControl(implicit p: Parameters) extends CoreBundle()(p) { def enabled(mstatus: MStatus) = !mstatus.debug && Cat(m, h, s, u)(mstatus.prv) } +class TExtra(implicit p: Parameters) extends CoreBundle()(p) { + def mvalueBits: Int = if (xLen == 32) coreParams.mcontextWidth min 6 else coreParams.mcontextWidth min 13 + def svalueBits: Int = if (xLen == 32) coreParams.scontextWidth min 16 else coreParams.scontextWidth min 34 + def mselectPos: Int = if (xLen == 32) 25 else 50 + def mvaluePos : Int = mselectPos + 1 + def sselectPos: Int = 0 + def svaluePos : Int = 2 + + val mvalue = UInt(mvalueBits.W) + val mselect = Bool() + val pad2 = UInt((mselectPos - svalueBits - 2).W) + val svalue = UInt(svalueBits.W) + val pad1 = UInt(1.W) + val sselect = Bool() +} + class BP(implicit p: Parameters) extends CoreBundle()(p) { val control = new BPControl val address = UInt(vaddrBits.W) + val textra = new TExtra + + def contextMatch(mcontext: UInt, scontext: UInt) = + (if (coreParams.mcontextWidth > 0) (!textra.mselect || (mcontext(textra.mvalueBits-1,0) === textra.mvalue)) else true.B) && + (if (coreParams.scontextWidth > 0) (!textra.sselect || (scontext(textra.svalueBits-1,0) === textra.svalue)) else true.B) def mask(dummy: Int = 0) = (0 until control.maskMax-1).scanLeft(control.tmatch(0))((m, i) => m && address(i)).asUInt @@ -62,6 +83,8 @@ class BreakpointUnit(n: Int)(implicit val p: Parameters) extends Module with Has val bp = Input(Vec(n, new BP)) val pc = Input(UInt(vaddrBits.W)) val ea = Input(UInt(vaddrBits.W)) + val mcontext = Input(UInt(coreParams.mcontextWidth.W)) + val scontext = Input(UInt(coreParams.scontextWidth.W)) val xcpt_if = Output(Bool()) val xcpt_ld = Output(Bool()) val xcpt_st = Output(Bool()) @@ -80,9 +103,10 @@ class BreakpointUnit(n: Int)(implicit val p: Parameters) extends Module with Has (io.bpwatch zip io.bp).foldLeft((true.B, true.B, true.B)) { case ((ri, wi, xi), (bpw, bp)) => val en = bp.control.enabled(io.status) - val r = en && bp.control.r && bp.addressMatch(io.ea) - val w = en && bp.control.w && bp.addressMatch(io.ea) - val x = en && bp.control.x && bp.addressMatch(io.pc) + val cx = bp.contextMatch(io.mcontext, io.scontext) + val r = en && bp.control.r && bp.addressMatch(io.ea) && cx + val w = en && bp.control.w && bp.addressMatch(io.ea) && cx + val x = en && bp.control.x && bp.addressMatch(io.pc) && cx val end = !bp.control.chain val action = bp.control.action diff --git a/src/main/scala/rocket/CSR.scala b/src/main/scala/rocket/CSR.scala index 296b4a8538..55a6062b5f 100644 --- a/src/main/scala/rocket/CSR.scala +++ b/src/main/scala/rocket/CSR.scala @@ -228,6 +228,8 @@ class CSRFileIO(implicit p: Parameters) extends CoreBundle val csrw_counter = UInt(OUTPUT, CSR.nCtr) val inst = Vec(retireWidth, UInt(width = iLen)).asInput val trace = Vec(retireWidth, new TracedInstruction).asOutput + val mcontext = Output(UInt(coreParams.mcontextWidth.W)) + val scontext = Output(UInt(coreParams.scontextWidth.W)) val vector = usingVector.option(new Bundle { val vconfig = new VConfig().asOutput @@ -363,6 +365,9 @@ class CSRFile( val reg_dscratch = Reg(UInt(width = xLen)) val reg_singleStepped = Reg(Bool()) + val reg_mcontext = (coreParams.mcontextWidth > 0).option(RegInit(0.U(coreParams.mcontextWidth.W))) + val reg_scontext = (coreParams.scontextWidth > 0).option(RegInit(0.U(coreParams.scontextWidth.W))) + val reg_tselect = Reg(UInt(width = log2Up(nBreakpoints))) val reg_bp = Reg(Vec(1 << log2Up(nBreakpoints), new BP)) val reg_pmp = Reg(Vec(nPMPs, new PMPReg)) @@ -439,6 +444,8 @@ class CSRFile( io.interrupt := (anyInterrupt && !io.singleStep || reg_singleStepped) && !(reg_debug || io.status.cease) io.interrupt_cause := interruptCause io.bp := reg_bp take nBreakpoints + io.mcontext := reg_mcontext.getOrElse(0.U) + io.scontext := reg_scontext.getOrElse(0.U) io.pmp := reg_pmp.map(PMP(_)) val isaMaskString = @@ -463,6 +470,7 @@ class CSRFile( CSRs.tselect -> reg_tselect, CSRs.tdata1 -> reg_bp(reg_tselect).control.asUInt, CSRs.tdata2 -> reg_bp(reg_tselect).address.sextTo(xLen), + CSRs.tdata3 -> reg_bp(reg_tselect).textra.asUInt, CSRs.misa -> reg_misa, CSRs.mstatus -> read_mstatus, CSRs.mtvec -> read_mtvec, @@ -479,6 +487,10 @@ class CSRFile( CSRs.dpc -> readEPC(reg_dpc).sextTo(xLen), CSRs.dscratch -> reg_dscratch.asUInt) + val context_csrs = LinkedHashMap[Int,Bits]() ++ + reg_mcontext.map(r => CSRs.mcontext -> r) ++ + reg_scontext.map(r => CSRs.scontext -> r) + val read_fcsr = Cat(reg_frm, reg_fflags) val fp_csrs = LinkedHashMap[Int,Bits]() ++ usingFPU.option(CSRs.fflags -> reg_fflags) ++ @@ -496,6 +508,7 @@ class CSRFile( CSRs.vlenb -> (vLen / 8).U) read_mapping ++= debug_csrs + read_mapping ++= context_csrs read_mapping ++= fp_csrs read_mapping ++= vector_csrs @@ -940,6 +953,16 @@ class CSRFile( for ((bp, i) <- reg_bp.zipWithIndex) { when (i === reg_tselect && (!bp.control.dmode || reg_debug)) { when (decoded_addr(CSRs.tdata2)) { bp.address := wdata } + when (decoded_addr(CSRs.tdata3)) { + if (coreParams.mcontextWidth > 0) { + bp.textra.mselect := wdata(bp.textra.mselectPos) + bp.textra.mvalue := wdata >> bp.textra.mvaluePos + } + if (coreParams.scontextWidth > 0) { + bp.textra.sselect := wdata(bp.textra.sselectPos) + bp.textra.svalue := wdata >> bp.textra.svaluePos + } + } when (decoded_addr(CSRs.tdata1)) { bp.control := wdata.asTypeOf(bp.control) @@ -956,6 +979,8 @@ class CSRFile( } } } + reg_mcontext.foreach { r => when (decoded_addr(CSRs.mcontext)) { r := wdata }} + reg_scontext.foreach { r => when (decoded_addr(CSRs.scontext)) { r := wdata }} if (reg_pmp.nonEmpty) for (((pmp, next), i) <- (reg_pmp zip (reg_pmp.tail :+ reg_pmp.last)) zipWithIndex) { require(xLen % pmp.cfg.getWidth == 0) when (decoded_addr(CSRs.pmpcfg0 + pmpCfgIndex(i)) && !pmp.cfgLocked) { @@ -1036,6 +1061,10 @@ class CSRFile( bpc.x := false } } + for (bpx <- reg_bp map {_.textra}) { + if (coreParams.mcontextWidth == 0) bpx.mselect := false.B + if (coreParams.scontextWidth == 0) bpx.sselect := false.B + } for (bp <- reg_bp drop nBreakpoints) bp := new BP().fromBits(0) for (pmp <- reg_pmp) { diff --git a/src/main/scala/rocket/Instructions.scala b/src/main/scala/rocket/Instructions.scala index 57f1c0726a..2792dab900 100644 --- a/src/main/scala/rocket/Instructions.scala +++ b/src/main/scala/rocket/Instructions.scala @@ -911,6 +911,9 @@ object CSRs { val tdata1 = 0x7a1 val tdata2 = 0x7a2 val tdata3 = 0x7a3 + val scontext = 0x5a8 + val hcontext = 0x6a8 + val mcontext = 0x7a8 val dcsr = 0x7b0 val dpc = 0x7b1 val dscratch = 0x7b2 @@ -1167,6 +1170,9 @@ object CSRs { res += tdata1 res += tdata2 res += tdata3 + res += scontext + res += hcontext + res += mcontext res += dcsr res += dpc res += dscratch diff --git a/src/main/scala/rocket/RocketCore.scala b/src/main/scala/rocket/RocketCore.scala index 725471ab80..83df946ec1 100644 --- a/src/main/scala/rocket/RocketCore.scala +++ b/src/main/scala/rocket/RocketCore.scala @@ -29,6 +29,8 @@ case class RocketCoreParams( nLocalInterrupts: Int = 0, nBreakpoints: Int = 1, useBPWatch: Boolean = false, + mcontextWidth: Int = 0, + scontextWidth: Int = 0, nPMPs: Int = 8, nPerfCounters: Int = 0, haveBasicCounters: Boolean = true, @@ -319,6 +321,8 @@ class Rocket(tile: RocketTile)(implicit p: Parameters) extends CoreModule()(p) bpu.io.bp := csr.io.bp bpu.io.pc := ibuf.io.pc bpu.io.ea := mem_reg_wdata + bpu.io.mcontext := csr.io.mcontext + bpu.io.scontext := csr.io.scontext val id_xcpt0 = ibuf.io.inst(0).bits.xcpt0 val id_xcpt1 = ibuf.io.inst(0).bits.xcpt1 diff --git a/src/main/scala/tile/Core.scala b/src/main/scala/tile/Core.scala index ef607c6461..a967bd7a8d 100644 --- a/src/main/scala/tile/Core.scala +++ b/src/main/scala/tile/Core.scala @@ -35,6 +35,8 @@ trait CoreParams { val pmpGranularity: Int val nBreakpoints: Int val useBPWatch: Boolean + val mcontextWidth: Int + val scontextWidth: Int val nPerfCounters: Int val haveBasicCounters: Boolean val haveFSDirty: Boolean