From acca0fccf5687fa4eb509ac2b5146cbf05922287 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Wed, 26 Jul 2017 02:13:43 -0700 Subject: [PATCH 1/3] Fix BTB not being refilled on some indirect jumps We are overloading the BTB-hit signal to mean that any part of the frontend changed the control-flow, not just the BTB. That's the right thing to do for most of the control logic, but it means the BTB sometimes won't get refilled when we'd like it to. This commit makes the frontend use an invalid BTB entry number when it, rather than the BTB, changes the control flow. Since the entry number is invalid, the BTB will treat it as a miss and refill itself. This is kind of a hack, but a more palatable fix requires reworking the RVC IBuf, which I don't have time for right now. --- src/main/scala/rocket/BTB.scala | 7 +++---- src/main/scala/rocket/Frontend.scala | 1 + 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/scala/rocket/BTB.scala b/src/main/scala/rocket/BTB.scala index aee91639..656556ec 100644 --- a/src/main/scala/rocket/BTB.scala +++ b/src/main/scala/rocket/BTB.scala @@ -11,7 +11,7 @@ import freechips.rocketchip.tile.HasCoreParameters import freechips.rocketchip.util._ case class BTBParams( - nEntries: Int = 32, + nEntries: Int = 30, nMatchBits: Int = 14, nPages: Int = 6, nRAS: Int = 6, @@ -24,7 +24,6 @@ trait HasBtbParameters extends HasCoreParameters { val entries = btbParams.nEntries val updatesOutOfOrder = btbParams.updatesOutOfOrder val nPages = (btbParams.nPages + 1) / 2 * 2 // control logic assumes 2 divides pages - val opaqueBits = log2Up(entries) } abstract class BtbModule(implicit val p: Parameters) extends Module with HasBtbParameters @@ -141,7 +140,7 @@ class BTBResp(implicit p: Parameters) extends BtbBundle()(p) { val mask = Bits(width = fetchWidth) val bridx = Bits(width = log2Up(fetchWidth)) val target = UInt(width = vaddrBits) - val entry = UInt(width = opaqueBits) + val entry = UInt(width = log2Up(entries + 1)) val bht = new BHTResp } @@ -196,7 +195,7 @@ class BTB(implicit p: Parameters) extends BtbModule { if (updatesOutOfOrder) { val updateHits = (pageHit << 1)(Mux1H(idxMatch(r_btb_update.bits.pc), idxPages)) (updateHits.orR, OHToUInt(updateHits)) - } else (r_btb_update.bits.prediction.valid, r_btb_update.bits.prediction.bits.entry) + } else (r_btb_update.bits.prediction.valid && r_btb_update.bits.prediction.bits.entry < entries, r_btb_update.bits.prediction.bits.entry) val useUpdatePageHit = updatePageHit.orR val usePageHit = pageHit.orR diff --git a/src/main/scala/rocket/Frontend.scala b/src/main/scala/rocket/Frontend.scala index db58b854..c7a39274 100644 --- a/src/main/scala/rocket/Frontend.scala +++ b/src/main/scala/rocket/Frontend.scala @@ -259,6 +259,7 @@ class FrontendModule(outer: Frontend) extends LazyModuleImp(outer) when (taken) { fq.io.enq.bits.btb.valid := true fq.io.enq.bits.btb.bits.taken := true + fq.io.enq.bits.btb.bits.entry := UInt(tileParams.btb.get.nEntries) s2_redirect := true } } From 5a9c673f41893905cd48efac4850e4d370470696 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Wed, 26 Jul 2017 02:20:41 -0700 Subject: [PATCH 2/3] Fix L2 TLB response bug Sometimes, it would inform the L1 TLB that the translation was for a superpage, even though that's never the case. --- src/main/scala/rocket/PTW.scala | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/scala/rocket/PTW.scala b/src/main/scala/rocket/PTW.scala index 01d284ae..1b0ba9f9 100644 --- a/src/main/scala/rocket/PTW.scala +++ b/src/main/scala/rocket/PTW.scala @@ -261,6 +261,7 @@ class PTW(n: Int)(implicit edge: TLEdgeOut, p: Parameters) extends CoreModule()( resp_valid(r_req_dest) := true resp_ae := false r_pte := l2_pte + count := pgLevels-1 } } From 5a5b78b15eabc08fd4300b0a81867f3b231b5132 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Wed, 26 Jul 2017 02:22:43 -0700 Subject: [PATCH 3/3] Improve L2 TLB coding style --- src/main/scala/rocket/PTW.scala | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/src/main/scala/rocket/PTW.scala b/src/main/scala/rocket/PTW.scala index 1b0ba9f9..cec3271b 100644 --- a/src/main/scala/rocket/PTW.scala +++ b/src/main/scala/rocket/PTW.scala @@ -136,7 +136,13 @@ class PTW(n: Int)(implicit edge: TLEdgeOut, p: Parameters) extends CoreModule()( val l2_refill = RegNext(false.B) io.dpath.perf.l2miss := false val (l2_hit, l2_pte) = if (coreParams.nL2TLBEntries == 0) (false.B, Wire(new PTE)) else { + val code = new ParityCode + require(isPow2(coreParams.nL2TLBEntries)) + val idxBits = log2Ceil(coreParams.nL2TLBEntries) + val tagBits = vpnBits - idxBits + class Entry extends Bundle { + val tag = UInt(width = tagBits) val ppn = UInt(width = ppnBits) val d = Bool() val a = Bool() @@ -144,20 +150,19 @@ class PTW(n: Int)(implicit edge: TLEdgeOut, p: Parameters) extends CoreModule()( val x = Bool() val w = Bool() val r = Bool() + + override def cloneType = new Entry().asInstanceOf[this.type] } - val code = new ParityCode - require(isPow2(coreParams.nL2TLBEntries)) - val idxBits = log2Ceil(coreParams.nL2TLBEntries) - val tagBits = vpnBits - idxBits - val ram = SeqMem(coreParams.nL2TLBEntries, UInt(width = code.width(new Entry().getWidth + tagBits))) + val ram = SeqMem(coreParams.nL2TLBEntries, UInt(width = code.width(new Entry().getWidth))) val g = Reg(UInt(width = coreParams.nL2TLBEntries)) val valid = RegInit(UInt(0, coreParams.nL2TLBEntries)) val (r_tag, r_idx) = Split(r_req.addr, idxBits) when (l2_refill) { val entry = Wire(new Entry) entry := r_pte - ram.write(r_idx, code.encode(Cat(entry.asUInt, r_tag))) + entry.tag := r_tag + ram.write(r_idx, code.encode(entry.asUInt)) val mask = UIntToOH(r_idx) valid := valid | mask @@ -176,11 +181,11 @@ class PTW(n: Int)(implicit edge: TLEdgeOut, p: Parameters) extends CoreModule()( val s2_rdata = code.decode(RegEnable(s1_rdata, s1_valid)) when (s2_valid && s2_rdata.error) { valid := 0.U } - val (s2_entry, s2_tag) = Split(s2_rdata.uncorrected, tagBits) - val s2_hit = s2_valid && !s2_rdata.error && r_tag === s2_tag - io.dpath.perf.l2miss := s2_valid && !(r_tag === s2_tag) + val s2_entry = s2_rdata.uncorrected.asTypeOf(new Entry) + val s2_hit = s2_valid && !s2_rdata.error && r_tag === s2_entry.tag + io.dpath.perf.l2miss := s2_valid && !(r_tag === s2_entry.tag) val s2_pte = Wire(new PTE) - s2_pte := s2_entry.asTypeOf(new Entry) + s2_pte := s2_entry s2_pte.g := g(r_idx) s2_pte.v := true