From 5980dc160f6cc5fa9ddaca0816cacf8f4b0e8632 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Thu, 6 Oct 2016 09:41:46 -0700 Subject: [PATCH] Don't allow multiple entries for same PC in BTB Necessary for RVC forward-progress guarantee. --- src/main/scala/rocket/btb.scala | 5 +++++ src/main/scala/util/Package.scala | 17 +++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/src/main/scala/rocket/btb.scala b/src/main/scala/rocket/btb.scala index 4131978d..3bf9e351 100644 --- a/src/main/scala/rocket/btb.scala +++ b/src/main/scala/rocket/btb.scala @@ -246,6 +246,11 @@ class BTB(implicit p: Parameters) extends BtbModule { io.resp.bits.bridx := (if (fetchWidth > 1) Mux1H(hitsVec, brIdx) else UInt(0)) io.resp.bits.mask := Cat((UInt(1) << ~Mux(io.resp.bits.taken, ~io.resp.bits.bridx, UInt(0)))-1, UInt(1)) + // if multiple entries for same PC land in BTB, zap them + when (PopCountAtLeast(hits, 2)) { + isValid := isValid & ~hits + } + if (nBHT > 0) { val bht = new BHT(nBHT) val isBranch = !(hits & isJump).orR diff --git a/src/main/scala/util/Package.scala b/src/main/scala/util/Package.scala index 4c9c1916..53ff0b9b 100644 --- a/src/main/scala/util/Package.scala +++ b/src/main/scala/util/Package.scala @@ -41,4 +41,21 @@ package object util { // this one's snagged from scalaz def option[T](z: => T): Option[T] = if (x) Some(z) else None } + + object PopCountAtLeast { + private def two(x: UInt): (Bool, Bool) = x.getWidth match { + case 1 => (Bool(true), Bool(false)) + case n => + val half = x.getWidth / 2 + val (leftOne, leftTwo) = two(x(half - 1, 0)) + val (rightOne, rightTwo) = two(x(x.getWidth - 1, half)) + (leftOne || rightOne, leftTwo || rightTwo || (leftOne && rightOne)) + } + def apply(x: UInt, n: Int): Bool = n match { + case 0 => Bool(true) + case 1 => x.orR + case 2 => two(x)._2 + case 3 => PopCount(x) >= UInt(n) + } + } }