diff --git a/diplomatic/src/rocket/CSR.scala b/diplomatic/src/rocket/CSR.scala index 3cedca6d6..ad47fb11c 100644 --- a/diplomatic/src/rocket/CSR.scala +++ b/diplomatic/src/rocket/CSR.scala @@ -15,49 +15,6 @@ import scala.collection.mutable.LinkedHashMap import Instructions._ import CustomInstructions._ -class MStatus extends Bundle { - // not truly part of mstatus, but convenient - val debug = Bool() - val cease = Bool() - val wfi = Bool() - val isa = UInt(32.W) - - val dprv = UInt(PRV.SZ.W) // effective prv for data accesses - val dv = Bool() // effective v for data accesses - val prv = UInt(PRV.SZ.W) - val v = Bool() - - val sd = Bool() - val zero2 = UInt(23.W) - val mpv = Bool() - val gva = Bool() - val mbe = Bool() - val sbe = Bool() - val sxl = UInt(2.W) - val uxl = UInt(2.W) - val sd_rv32 = Bool() - val zero1 = UInt(8.W) - val tsr = Bool() - val tw = Bool() - val tvm = Bool() - val mxr = Bool() - val sum = Bool() - val mprv = Bool() - val xs = UInt(2.W) - val fs = UInt(2.W) - val mpp = UInt(2.W) - val vs = UInt(2.W) - val spp = UInt(1.W) - val mpie = Bool() - val ube = Bool() - val spie = Bool() - val upie = Bool() - val mie = Bool() - val hie = Bool() - val sie = Bool() - val uie = Bool() -} - class MNStatus extends Bundle { val mpp = UInt(2.W) val zero3 = UInt(3.W) @@ -141,64 +98,6 @@ class PTBR(implicit p: Parameters) extends CoreBundle()(p) { val ppn = UInt((maxPAddrBits - pgIdxBits).W) } -object PRV -{ - val SZ = 2 - val U = 0 - val S = 1 - val H = 2 - val M = 3 -} - -object CSR -{ - // commands - val SZ = 3 - def X = BitPat.dontCare(SZ) - def N = 0.U(SZ.W) - def R = 2.U(SZ.W) - def I = 4.U(SZ.W) - def W = 5.U(SZ.W) - def S = 6.U(SZ.W) - def C = 7.U(SZ.W) - - // mask a CSR cmd with a valid bit - def maskCmd(valid: Bool, cmd: UInt): UInt = { - // all commands less than CSR.I are treated by CSRFile as NOPs - cmd & ~Mux(valid, 0.U, CSR.I) - } - - val ADDRSZ = 12 - - def modeLSB: Int = 8 - def mode(addr: Int): Int = (addr >> modeLSB) % (1 << PRV.SZ) - def mode(addr: UInt): UInt = addr(modeLSB + PRV.SZ - 1, modeLSB) - - def busErrorIntCause = 128 - def debugIntCause = 14 // keep in sync with MIP.debug - def debugTriggerCause = { - val res = debugIntCause - require(!(Causes.all contains res)) - res - } - def rnmiIntCause = 13 // NMI: Higher numbers = higher priority, must not reuse debugIntCause - def rnmiBEUCause = 12 - - val firstCtr = CSRs.cycle - val firstCtrH = CSRs.cycleh - val firstHPC = CSRs.hpmcounter3 - val firstHPCH = CSRs.hpmcounter3h - val firstHPE = CSRs.mhpmevent3 - val firstMHPC = CSRs.mhpmcounter3 - val firstMHPCH = CSRs.mhpmcounter3h - val firstHPM = 3 - val nCtr = 32 - val nHPM = nCtr - firstHPM - val hpmWidth = 40 - - val maxPMPs = 16 -} - class PerfCounterIO(implicit p: Parameters) extends CoreBundle with HasCoreParameters { val eventSel = Output(UInt(xLen.W)) @@ -278,7 +177,7 @@ class CSRFileIO(implicit p: Parameters) extends CoreBundle val rocc_interrupt = Input(Bool()) val interrupt = Output(Bool()) val interrupt_cause = Output(UInt(xLen.W)) - val bp = Output(Vec(nBreakpoints, new BP)) + val bp = Output(Vec(nBreakpoints, new BP(p(XLen),coreParams.mcontextWidth, coreParams.scontextWidth,coreParams.useBPWatch, vaddrBits ))) val pmp = Output(Vec(nPMPs, new PMP)) val counters = Vec(nPerfCounters, new PerfCounterIO) val csrw_counter = Output(UInt(CSR.nCtr.W)) @@ -458,7 +357,7 @@ class CSRFile( val reg_scontext = (coreParams.scontextWidth > 0).option(RegInit(0.U(coreParams.scontextWidth.W))) val reg_tselect = Reg(UInt(log2Up(nBreakpoints).W)) - val reg_bp = Reg(Vec(1 << log2Up(nBreakpoints), new BP)) + val reg_bp = Reg(Vec(1 << log2Up(nBreakpoints), new BP(p(XLen),coreParams.mcontextWidth, coreParams.scontextWidth,coreParams.useBPWatch, vaddrBits ))) val reg_pmp = Reg(Vec(nPMPs, new PMPReg)) val reg_mie = Reg(UInt(xLen.W)) @@ -1512,7 +1411,7 @@ class CSRFile( if (coreParams.scontextWidth == 0) bpx.sselect := false.B } for (bp <- reg_bp drop nBreakpoints) - bp := 0.U.asTypeOf(new BP()) + bp := 0.U.asTypeOf(new BP(p(XLen),coreParams.mcontextWidth, coreParams.scontextWidth,coreParams.useBPWatch, vaddrBits )) for (pmp <- reg_pmp) { pmp.cfg.res := 0.U when (reset.asBool) { pmp.reset() } diff --git a/diplomatic/src/rocket/RocketCore.scala b/diplomatic/src/rocket/RocketCore.scala index 523819d94..b732f4993 100644 --- a/diplomatic/src/rocket/RocketCore.scala +++ b/diplomatic/src/rocket/RocketCore.scala @@ -349,7 +349,7 @@ class Rocket(tile: RocketTile)(implicit p: Parameters) extends CoreModule()(p) val id_do_fence = WireDefault(id_rocc_busy && id_ctrl.fence || id_mem_busy && (id_ctrl.amo && id_amo_rl || id_ctrl.fence_i || id_reg_fence && (id_ctrl.mem || id_ctrl.rocc))) - val bpu = Module(new BreakpointUnit(nBreakpoints)) + val bpu = Module(new BreakpointUnit(nBreakpoints,p(XLen),coreParams.mcontextWidth, coreParams.scontextWidth,coreParams.useBPWatch, vaddrBits )) bpu.io.status := csr.io.status bpu.io.bp := csr.io.bp bpu.io.pc := ibuf.io.pc diff --git a/diplomatic/src/rocket/Breakpoint.scala b/rocket/src/Breakpoint.scala similarity index 57% rename from diplomatic/src/rocket/Breakpoint.scala rename to rocket/src/Breakpoint.scala index fc18209bd..2aeb978f9 100644 --- a/diplomatic/src/rocket/Breakpoint.scala +++ b/rocket/src/Breakpoint.scala @@ -4,16 +4,67 @@ package org.chipsalliance.rocket import chisel3._ import chisel3.util.{Cat} -import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.tile.{CoreBundle, HasCoreParameters} -import freechips.rocketchip.util._ - -class BPControl(implicit p: Parameters) extends CoreBundle()(p) { +import org.chipsalliance.rocket.util._ + +//todo: remove this +object PRV +{ + val SZ = 2 + val U = 0 + val S = 1 + val H = 2 + val M = 3 +} +//todo: remove this +class MStatus extends Bundle { + // not truly part of mstatus, but convenient + val debug = Bool() + val cease = Bool() + val wfi = Bool() + val isa = UInt(32.W) + + val dprv = UInt(PRV.SZ.W) // effective prv for data accesses + val dv = Bool() // effective v for data accesses + val prv = UInt(PRV.SZ.W) + val v = Bool() + + val sd = Bool() + val zero2 = UInt(23.W) + val mpv = Bool() + val gva = Bool() + val mbe = Bool() + val sbe = Bool() + val sxl = UInt(2.W) + val uxl = UInt(2.W) + val sd_rv32 = Bool() + val zero1 = UInt(8.W) + val tsr = Bool() + val tw = Bool() + val tvm = Bool() + val mxr = Bool() + val sum = Bool() + val mprv = Bool() + val xs = UInt(2.W) + val fs = UInt(2.W) + val mpp = UInt(2.W) + val vs = UInt(2.W) + val spp = UInt(1.W) + val mpie = Bool() + val ube = Bool() + val spie = Bool() + val upie = Bool() + val mie = Bool() + val hie = Bool() + val sie = Bool() + val uie = Bool() +} +//todo: remove util +class BPControl(xLen:Int, useBPWatch: Boolean) extends Bundle { val ttype = UInt(4.W) val dmode = Bool() val maskmax = UInt(6.W) - val reserved = UInt((xLen - (if (coreParams.useBPWatch) 26 else 24)).W) - val action = UInt((if (coreParams.useBPWatch) 3 else 1).W) + val reserved = UInt((xLen - (if (useBPWatch) 26 else 24)).W) + val action = UInt((if (useBPWatch) 3 else 1).W) val chain = Bool() val zero = UInt(2.W) val tmatch = UInt(2.W) @@ -30,9 +81,9 @@ 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 +class TExtra(xLen:Int, mcontextWidth:Int, scontextWidth:Int) extends Bundle { + def mvalueBits: Int = if (xLen == 32) mcontextWidth min 6 else mcontextWidth min 13 + def svalueBits: Int = if (xLen == 32) scontextWidth min 16 else scontextWidth min 34 def mselectPos: Int = if (xLen == 32) 25 else 50 def mvaluePos : Int = mselectPos + 1 def sselectPos: Int = 0 @@ -46,14 +97,14 @@ class TExtra(implicit p: Parameters) extends CoreBundle()(p) { val sselect = Bool() } -class BP(implicit p: Parameters) extends CoreBundle()(p) { - val control = new BPControl +class BP(xLen: Int, mcontextWidth: Int, scontextWidth: Int, useBPWatch: Boolean, vaddrBits: Int) extends Bundle { + val control = new BPControl(xLen, useBPWatch) val address = UInt(vaddrBits.W) - val textra = new TExtra + val textra = new TExtra(xLen, mcontextWidth, scontextWidth) 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) + (if (mcontextWidth > 0) (!textra.mselect || (mcontext(textra.mvalueBits-1,0) === textra.mvalue)) else true.B) && + (if (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 @@ -76,14 +127,14 @@ class BPWatch (val n: Int) extends Bundle() { val action = UInt(3.W) } -class BreakpointUnit(n: Int)(implicit val p: Parameters) extends Module with HasCoreParameters { +class BreakpointUnit(n: Int, xLen: Int, mcontextWidth: Int, scontextWidth: Int, useBPWatch: Boolean, vaddrBits: Int) extends Module { val io = IO(new Bundle { val status = Input(new MStatus()) - val bp = Input(Vec(n, new BP)) + val bp = Input(Vec(n, new BP(xLen, mcontextWidth, scontextWidth, useBPWatch, vaddrBits))) 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 mcontext = Input(UInt(mcontextWidth.W)) + val scontext = Input(UInt(scontextWidth.W)) val xcpt_if = Output(Bool()) val xcpt_ld = Output(Bool()) val xcpt_st = Output(Bool()) diff --git a/rocket/src/util.scala b/rocket/src/util.scala new file mode 100644 index 000000000..7cc7de147 --- /dev/null +++ b/rocket/src/util.scala @@ -0,0 +1,153 @@ +package org.chipsalliance.rocket + +import chisel3._ +import chisel3.util._ + +//todo: remove util +package object util { + implicit class SeqToAugmentedSeq[T <: Data](private val x: Seq[T]) extends AnyVal { + def apply(idx: UInt): T = { + if (x.size <= 1) { + x.head + } else if (!isPow2(x.size)) { + // For non-power-of-2 seqs, reflect elements to simplify decoder + (x ++ x.takeRight(x.size & -x.size)).toSeq(idx) + } else { + // Ignore MSBs of idx + val truncIdx = + if (idx.isWidthKnown && idx.getWidth <= log2Ceil(x.size)) idx + else (idx | 0.U(log2Ceil(x.size).W))(log2Ceil(x.size)-1, 0) + x.zipWithIndex.tail.foldLeft(x.head) { case (prev, (cur, i)) => Mux(truncIdx === i.U, cur, prev) } + } + } + + def asUInt: UInt = Cat(x.map(_.asUInt).reverse) + + def rotate(n: Int): Seq[T] = x.drop(n) ++ x.take(n) + + def rotate(n: UInt): Seq[T] = { + if (x.size <= 1) { + x + } else { + require(isPow2(x.size)) + val amt = n.padTo(log2Ceil(x.size)) + (0 until log2Ceil(x.size)).foldLeft(x)((r, i) => (r.rotate(1 << i) zip r).map { case (s, a) => Mux(amt(i), s, a) }) + } + } + + def rotateRight(n: Int): Seq[T] = x.takeRight(n) ++ x.dropRight(n) + + def rotateRight(n: UInt): Seq[T] = { + if (x.size <= 1) { + x + } else { + require(isPow2(x.size)) + val amt = n.padTo(log2Ceil(x.size)) + (0 until log2Ceil(x.size)).foldLeft(x)((r, i) => (r.rotateRight(1 << i) zip r).map { case (s, a) => Mux(amt(i), s, a) }) + } + } + } + + implicit class UIntToAugmentedUInt(private val x: UInt) extends AnyVal { + def sextTo(n: Int): UInt = { + require(x.getWidth <= n) + if (x.getWidth == n) x + else Cat(Fill(n - x.getWidth, x(x.getWidth - 1)), x) + } + + def padTo(n: Int): UInt = { + require(x.getWidth <= n) + if (x.getWidth == n) x + else Cat(0.U((n - x.getWidth).W), x) + } + + // shifts left by n if n >= 0, or right by -n if n < 0 + def <<(n: SInt): UInt = { + val w = n.getWidth - 1 + require(w <= 30) + + val shifted = x << n(w - 1, 0) + Mux(n(w), shifted >> (1 << w), shifted) + } + + // shifts right by n if n >= 0, or left by -n if n < 0 + def >>(n: SInt): UInt = { + val w = n.getWidth - 1 + require(w <= 30) + + val shifted = x << (1 << w) >> n(w - 1, 0) + Mux(n(w), shifted, shifted >> (1 << w)) + } + + // Like UInt.apply(hi, lo), but returns 0.U for zero-width extracts + def extract(hi: Int, lo: Int): UInt = { + require(hi >= lo - 1) + if (hi == lo - 1) 0.U + else x(hi, lo) + } + + // Like Some(UInt.apply(hi, lo)), but returns None for zero-width extracts + def extractOption(hi: Int, lo: Int): Option[UInt] = { + require(hi >= lo - 1) + if (hi == lo - 1) None + else Some(x(hi, lo)) + } + + // like x & ~y, but first truncate or zero-extend y to x's width + def andNot(y: UInt): UInt = x & ~(y | (x & 0.U)) + + def rotateRight(n: Int): UInt = if (n == 0) x else Cat(x(n - 1, 0), x >> n) + + def rotateRight(n: UInt): UInt = { + if (x.getWidth <= 1) { + x + } else { + val amt = n.padTo(log2Ceil(x.getWidth)) + (0 until log2Ceil(x.getWidth)).foldLeft(x)((r, i) => Mux(amt(i), r.rotateRight(1 << i), r)) + } + } + + def rotateLeft(n: Int): UInt = if (n == 0) x else Cat(x(x.getWidth - 1 - n, 0), x(x.getWidth - 1, x.getWidth - n)) + + def rotateLeft(n: UInt): UInt = { + if (x.getWidth <= 1) { + x + } else { + val amt = n.padTo(log2Ceil(x.getWidth)) + (0 until log2Ceil(x.getWidth)).foldLeft(x)((r, i) => Mux(amt(i), r.rotateLeft(1 << i), r)) + } + } + + // compute (this + y) % n, given (this < n) and (y < n) + def addWrap(y: UInt, n: Int): UInt = { + val z = x +& y + if (isPow2(n)) z(n.log2 - 1, 0) else Mux(z >= n.U, z - n.U, z)(log2Ceil(n) - 1, 0) + } + + // compute (this - y) % n, given (this < n) and (y < n) + def subWrap(y: UInt, n: Int): UInt = { + val z = x -& y + if (isPow2(n)) z(n.log2 - 1, 0) else Mux(z(z.getWidth - 1), z + n.U, z)(log2Ceil(n) - 1, 0) + } + + def grouped(width: Int): Seq[UInt] = + (0 until x.getWidth by width).map(base => x(base + width - 1, base)) + + def inRange(base: UInt, bounds: UInt) = x >= base && x < bounds + + def ##(y: Option[UInt]): UInt = y.map(x ## _).getOrElse(x) + + // Like >=, but prevents x-prop for ('x >= 0) + def >==(y: UInt): Bool = x >= y || y === 0.U + } + + implicit class IntToAugmentedInt(private val x: Int) extends AnyVal { + // exact log2 + def log2: Int = { + require(isPow2(x)) + log2Ceil(x) + } + } + + +}